Liquid XML Studio 2019
How a JSON Schema is translated into a Data Mapper Component

When you create a JSON data source or target the component that is created can contain connectors that seem like duplicates. This topic will walkthrough how a JSON schema is translated into a data mapper component and show how the schema design can be improved the quality of the schema and as result simplify the model.

 

Example 1

This schema has a number of properties, the first 6 properties are strongly typed, by that I mean that they have an explicit type set on them.

Strongly typed schemas convert well into the data mapper an produce a single connection point in the resulting transform.

The next property 'UntypedProperty' does not contain any type information in the schema, this means it can contain data of any type (array, bool, integer, null, number, object, string).

Untyped values do not translate as well into the data mapper as every possible type has to be represented in the model. The result is duplicate connection points, one for each possible type.

The next property 'UnionProperty' allows integer types and string types. As you can see in the data mapper this is created as 2 connection points, one for string and one for integer.

Finally lets look at <Additional Properties> this means the object can contain any additional properties with any name or type. As you can see this translates to a connection point called 'Additional Properties' in the data mapper. An 'Additional Properties' value will exist for each property read from the data source, it has a child called 'Name' which will have a single value holding then name of the property read from the data source, and one or more 'Value' nodes, one for each type that the <Additional Properties> permits, only the 'Value' connection point corresponding to the type of the current property will contain a value for a given property.

Schema Source Code
Copy Code
{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "title": "My schema",
    "additionalProperties": true,
    "properties": {
        "ArrayProperty": {
            "type": "array"
        },
        "BooleanProperty": {
            "type": "boolean"
        },
        "IntegetProperty": {
            "type": "integer"
        },
        "NullProperty": {
            "type": "null"
        },
        "ObjectProperty": {
            "type": "object"
        },
        "StringProperty": {
            "type": "string"
        },
        "UntypedProperty": {},
        "UnionProperty": {
            "type": [
                "integer",
                "string"
            ]
        }
    }
}

If the following JSON data was loaded the values in the reader would look like this

Sample Data
Copy Code
{
    "ArrayProperty": [],
    "BooleanProperty": true,
    "IntegetProperty": 744,
    "NullProperty": null,
    "ObjectProperty": {},
    "StringProperty": "ABCDEFG",
    "UntypedProperty": false,
    "UnionProperty": 468,
    "OtherString" : "Value1",
    "OtherBool" : true
}
Data Source Representation
Copy Code
Root                                                : Node
    ArrayProperty (ArrayList)                       : Node
    BooleanProperty (Boolean)                       : true,
    IntegetProperty (integer)                       : 744,
    NullProperty (Null)                             :
    ObjectProperty (Object)                         : Node
    StringProperty (String)                         : "ABCDEFG",
    UntypedProperty (Boolean)                       : false,
    UnionProperty (Integer)                         : 468,
    Additional Properties (Additional Properties)   : Node
        Name (PropertyName)                         : "OtherString",
        Value (String)                              : "Value1"
    Additional Properties (Additional Properties)   : Node
        Name (PropertyName)                         : "OtherBool"
        Value (Boolean)                             : true

Example 2 Arrays

In the previous example we glossed over how the values in an array are translated into a Data Mapper component. This example digs a little deeper.

 

The JSON Schema standard defines 2 mechanisms for array validation tuple and list based. List based means that every item in the array must comply with a given schema. Tuple based validation means that each item of data must comply with the schema at the corresponding index.

  

The property 'ListArrayProperty' specifies that all items in the array must be strings. This translates into a hierarchy of connection points within the data mapper. The connection point 'ListArrayProperty (ArrayList)' contains a value if the property is present in the source data (even if its an empty array). This contains a child 'Item[0-n] (Any)' this contains a value for every element within the source data array (this may seem like an unnecessary child relation, but in more complex cases it is required). Within this is a child connection point 'Value (String)', this contains a string value representing the array item in the source data.

 

The property 'TupleArrayProperty' specifies that the array can have 0-3 items the first item must be a string, the second an Integer and the third a Boolean. The translation into the data mapper is more straight forward. The connection point 'TupleArrayProperty (ArrayTuple)' contains a value if the property is present in the source data (even if its an empty array). The child 'Item; connection points represent the items at a given index within the array.

 

If the array allows untyped items then as with the previous example a connection point is created for each type that is allowed.

 

 

If the following JSON data was loaded the values in the reader would look like this

 

Sample Data
Copy Code
{
    "ListArrayProperty": ["ItemA", "ItemB", "ItemC", "ItemD"],
    "TupleArrayProperty": ["ItemA", 34, false],
    "UntypedArrayProperty": ["ItemA", "ItemB", 32.2, true]
}
Data Source Representation
Copy Code
Root                                                : Node
    ListArrayProperty (ArrayList)                   : Node
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemA"
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemB"
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemC"
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemD"
    UpleArrayProperty (ArrayList)                   : Node
        Item[0] (String)                            : "ItemA"
        Item[1] (Integer)                           : 34
        Item[2] (Boolean)                           : false
    UntypedArrayProperty (ArrayList)                : Node
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemA"
        Item[0-n] (Any)                             : Node
            Value (String)                          : "ItemB"
        Item[0-n] (Any)                             : Node
            Value (Number)                          : 32.2
        Item[0-n] (Any)                             : Node
            Value (Boolean)                         : true