All Articles

Working with Nulls in JSON

header

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"
            }
          }
        }
      ]
    }
  }
}

Condition 1: Null to Null

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).

condition 1 null to null required

Figure 1: Required Option Set within the JSON profile to force a null element.

Condition 2: Empty String to Empty String

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.

condition 2 process overview

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.

condition 2 data process 1

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 "".

condition 2 data process 2

Figure 4: Data Process Shape for Replacing Marked Empty String Data.

Condition 3: Boolean Nulls to Boolean Nulls

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.

condition 3 boolean null

Figure 5: Required Option Set within the JSON profile on the Boolean Element.

Condition 4: Numeric Nulls to Numeric Nulls

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.

condition 4 numeric null

Figure 6: Required Option Set within the JSON profile on the Numeric Element.

Condition 5: Empty JSON Object to Empty JSON Object

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)
}

condition 5 empty object

Figure 7. Data Process Shape for Mapping Empty JSON Objects.

Condition 6: Empty Array to Empty Array

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)
}

Condition 7: Null Object to Null Object

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.

condition 7 null object

Figure 8: Required Option Set within the JSON profile on the Object Node.

Condition 8: Null Array to Null Array

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.

condition 8 null array

Figure 9: Required Option Set within the JSON profile on the Array Node.

The article was originally posted at Boomi Community.

Published Feb 10, 2024

Developing a better world.© All rights reserved.