Boomi profiles generally treat nulls and empty strings as the same. Therefore, when you map a null value within a map, the output will be interpreted as nothing was mapped and the element will not be present in the output JSON. This article outlines how to handle various JSON null conditions in Boomi when mapping JSON to JSON within a map shape.
The conditions below fall into three possible solutions depending on requirements. The first solution is to use the JSON Profile Required Option. The second solution is to use the Data Process Search/Replace. The third solution is to use the Data Process Custom Script.
The following table outlines the various JSON null conditions and the desired output:
Condition | JSON Input | Desired JSON Output | Solution |
---|---|---|---|
1 | null |
null |
JSON Profile - Required Option |
2 | Empty String ( "" ) |
"" |
Data Process - Search/Replace |
3 | Boolean (null ) |
null |
JSON Profile - Required Option |
4 | Numeric (null ) |
null |
JSON Profile - Required Option |
5 | Empty JSON Object ({} ) |
{} |
Data Process - Custom Script |
6 | Empty Array ([] ) |
[] |
Data Process - Custom Script |
7 | Null Object (null ) |
null |
JSON Profile - Required Option or Data process - Custom Script |
8 | Null Array (null ) |
null |
JSON Profile - Required Option or Data process - Custom Script |
The following JSON is going to be used throughout all of the examples. Each element represents a different JSON null condition.
{
"string": "hello",
"nullValue": null,
"emptyString": "",
"booleanNull": null,
"numericNull": null,
"emptyObject": {},
"emptyArray": [],
"nullObject": null,
"nullArray": null
}
The following schema is used in the null JSON examples.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"string": {
"type": "string"
},
"nullValue": {
"type": "string"
},
"emptyObject": {
"type": "object",
"properties": {
"element1": {
"type": "string"
}
}
},
"emptyString": {
"type": "string"
},
"nullObject": {
"type": "object",
"properties": {
"element1": {
"type": "string"
}
}
},
"booleanNull": {
"type": "boolean"
},
"numericNull": {
"type": "integer"
},
"emptyArray": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"element1": {
"type": "string"
}
}
}
]
},
"nullArray": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"element1": {
"type": "string"
}
}
}
]
}
}
}
Boomi will read a null value and an empty string as the same. Both are viewed as an empty string within a map function. Both will be viewed as if nothing was mapped and the element will not be present in the output JSON. The Data Process shape with Find/Replace can not be used within this situation because it would not be able to distinguish the difference between a null element, a null object, and a null array. If the business logic allows for a null or empty string to be mapped to a null, then this solution can fulfill the requirements. If the business logic requires a null to be mapped to a null and an empty string to be mapped to an empty string, then this solution can be used in conjunction with Condition 2 (Empty String to Empty String).
Figure 1: Required Option Set within the JSON profile to force a null element.
Boomi will read a null value and an empty string as the same. Within a map, the output will be either an unmapped element if the required option is not selected or a null if the required option is selected.
Figure 2: Process Overview for Mapping Empty Strings.
Before the map, the data process shape is used to mark the empty string data. The Search/Replace step is used to replace ""
with "EMPTY_STRING_TO_BE_REPLACED"
. EMPTY_STRING_TO_BE_REPLACED
is a generic string that is assumed to not be present in the data and would be safe to use as a marker.
Figure 3: Data Process Shape for Marking Empty String Data.
After the map has been executed, the data process shape is used to replace the EMPTY_STRING_TO_BE_REPLACED
with ""
.
Figure 4: Data Process Shape for Replacing Marked Empty String Data.
If a boolean data type is null, it can be mapped to a boolean null by setting the element as required. The required option will be for the element to be present in the output JSON. It assumes that the three possible values are true, false, and null.
Figure 5: Required Option Set within the JSON profile on the Boolean Element.
If a numeric data type is null, it can be mapped to a numeric null by setting the element as required. The required option will be for the element to be present in the output JSON. It assumes that the two possible values are a numeric value and null.
Figure 6: Required Option Set within the JSON profile on the Numeric Element.
Boomi does not natively support the ability to map an empty object to an empty object. A custom script will be required to handle this condition. The following script will map the string and emptyObject elements to a new JSON object and return it to the document flow. The script will need to be modified to handle the specific JSON elements that are required. This script will replace the functionality normally found within a map.
// Groovy 2.4
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import java.util.Properties
import java.io.InputStream
for (int i = 0; i < dataContext.getDataCount(); i++) {
InputStream is = dataContext.getStream(i)
Properties props = dataContext.getProperties(i)
def parsedJson = new JsonSlurper().parse(is)
// Map and build new JSON
// Only the string and emptyObject are mapped
def outputJson = [:]
outputJson.string = parsedJson.string
outputJson.emptyObject = parsedJson.emptyObject
// Convert the JSON to a stream to return to the document flow
dataContext.storeStream(new ByteArrayInputStream(JsonOutput.toJson(outputJson).getBytes("UTF-8")), props)
}
Figure 7. Data Process Shape for Mapping Empty JSON Objects.
Boomi does not natively support the ability to map an empty array to an empty array. A custom script will be required to handle this condition. The following script will map the string and emptyArray elements to a new JSON object and return it to the document flow. The script will need to be modified to handle the specific JSON elements that are required. This script will need to replace the functionality normally found within a map.
// Groovy 2.4
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import java.util.Properties
import java.io.InputStream
for (int i = 0; i < dataContext.getDataCount(); i++) {
InputStream is = dataContext.getStream(i)
Properties props = dataContext.getProperties(i)
def parsedJson = new JsonSlurper().parse(is)
// Map and build new JSON
// Only the string and emptyArray are mapped
def outputJson = [:]
outputJson.string = parsedJson.string
outputJson.emptyArray = parsedJson.emptyArray
// Convert the JSON to a stream to return to the document flow
dataContext.storeStream(new ByteArrayInputStream(JsonOutput.toJson(outputJson).getBytes("UTF-8")), props)
}
If only a null
is required to be populated and a distinction between an empty object and a null object is not required, then the Required option can be used. If a distinction between an empty object and a null object is required, then a custom script will be required to handle the condition.
Figure 8: Required Option Set within the JSON profile on the Object Node.
If only a null
is required to be populated and a distinction between an empty array and a null array is not required, then the Required option can be used. If a distinction between an empty array and a null array is required, then a custom script will be required to handle the condition.
Figure 9: Required Option Set within the JSON profile on the Array Node.
The article was originally posted at Boomi Community.