Monday, May 25, 2020

JSON mapping and Transform

JSON mapping and Transform

Current Issue and requirement


Nowadays most applications are using APIs to interact with internal distributed applications or interact with 3rd party applications. A most common need of APIs are their results needs to map with different custom JSON format. If you are working in .net C# like strongly typed language then you ended up in followings to map different format JSON.

1. Create Source C# POCO object
2. Create Result C# POCO Object
3. DeSerialize JSON to C# Object for both Source and destination class.
4. Create Mapper class which can Map two C# class and generates resulted in object by mapping property with a different name. Here you can use the "Automapper" library.

Use case scenario


This kind of need gets complexer when you dealing with multiple 3rd party APIs needs to map a single result type json. Here are couple of scenarios for the same.
1. Air ticket booking. Invoke multiple airline apis for the ticket booking request and associates the result object and show it to users.
2. Quotation or Pricing for an Item from multiple stores or vendor.
3. Hotel booking etc.

In above use case scenarios, If you wanted to build a system that may want to add new API vendor then Developers has to do work on all the above-mentioned steps, and application implementation is not closed for maintenance. (2. Open closed principle of SOLID principles)

Solutions:

For this issue I found Querying JSON with complex JSON path interesting way to map it. This is explained in [Newtonsoft Json](https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm). You can generate some kind of JSON transform JSON and can generate resulted JSON.

This has been resolved by WorkMaze/JUST.net

https://github.com/WorkMaze/JUST.net

It uses transformation language like XSLT. It also includes functions present JUST documentation to convert values in desired output JSON.

I have tried one small example myself which I explained below.
They have given lots of examples and almost all cases they provided in their open-source Test/Unit Test.

Microsoft also has a projected JSON transformation library called JDT - Transform JSON File using a JSON transformation file.

https://github.com/microsoft/json-document-transforms

It has a Wiki page also here. https://github.com/microsoft/json-document-transforms/wiki
This solution is basically transforming configuration files like "appsettings.json" used in asp.net core projects and their approach is merging two files instead of just transform. for example if you have defined Source Json and Transform JSON according to JD specification, It will result in Merge of matched properties of transform and none matched properties as well. You have to mention delete specifically for each not matched or not needed property in transform.

4. one code example

Source JSON:

    {
        "Name": "Atul Patel",
        "Addresses": [
            {
                "Address1": "234 Brewer st",
                "Address2": "",
                "zipcode": "75072",
                "City": "Mckinney",
                "State": "Texas",
                "Country": "USA",
                "AddressType": "PrimaryHomeAddress"
            },
            {
                "Address1": "343 McCullam st",
                "Address2": "",
                "zip": "75845",
                "City": "Dallas",
                "State": "Texas",
                "Country": "USA",
                "AddressType": "OfficeAddress"
            }
        ],
        "DateOfBirth": "07/07/1980"
    }
    

Transform JSON:

    {
    "Name": "#valueof($.Name)",
    "Addresse": {
        "Address1": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].Address1)",
        "Address2": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].Address2)",
        "zip": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].zipcode)",
        "City": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].City)",
        "State": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].State)",
        "Country": "#valueof($.Addresses[?(@.AddressType=='PrimaryHomeAddress')].Country)"
    },
    "BirthDate": "#valueof($.DateOfBirth)"
    }

Result JSON:

{
  "Name": "Atul Patel",
  "Addresse": {
    "Address1": "234 Brewer st",
    "Address2": "",
    "zip": "75072",
    "City": "Mckinney",
    "State": "Texas",
    "Country": "USA"
  },
  "BirthDate": "07/07/1980"
}

Conclusion:

Using JSON.net like a library can provide a cleaner approach of mapping different JSON formats by providing a JSON transform file. Anytime you have a new source, You don't need to do and code changes. Just provide a transformation file would be enough. This is satisfying one the SOLID principle (Open-Close principle).

References:


https://github.com/WorkMaze/JUST.net
https://www.codeproject.com/Articles/1187172/JUST-JSON-Under-Simple-Transformation
https://github.com/microsoft/json-document-transforms
https://github.com/microsoft/json-document-transforms/wiki
https://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm