Search code examples
jolt

Merge 2 objects based on condition using JOLT spec


I have an input JSON as below. I need to check if "code" inside "attributes" and the "code" inside "dynamicAttributes" is equal, then populate desired output.

Input :

{
  "attributes": [
    {
      "code": "INPUT",
      "name": "Code1",
      "valueDescription": "Input here"
    },
    {
      "code": "SEND",
      "name": "Code2",
      "valueDescription": "Send msg"
    },
    {
      "code": "OUTPUT",
      "name": "Code3",
      "valueDescription": "Output here"
    },
    {
      "code": "STAGE",
      "name": "Code4",
      "valueDescription": "Stage here"
    }
  ],
  "result": {
    "dynamicAttributes": [
      {
        "value": "1",
        "active": true,
        "code": "INPUT"
      },
      {
        "value": "0",
        "active": false,
        "code": "STAGE"
      },
      {
        "value": "0",
        "active": false,
        "code": "OUTPUT"
      }
    ]
  }
}

Desired Output :

{
    "result": {
        "dynamicAttributes": [
            {
                "value": "1",
                "active": true,
                "code": "INPUT",
                "name": "Code1",
                "valueDescription": "Input here"
            },
            {
                "value": "0",
                "active": false,
                "code": "OUTPUT",
                "name": "Code3",
                "valueDescription": "Output here"
            },
            {
                "value": "0",
                "active": false,
                "code": "STAGE",
                "name": "Code4",
                "valueDescription": "Stage here"
            }
        ]
    }
}

Below is what I have tried so far with the jolt-spec :

  1. Get the "code" value to LHS and use an array to keep values from attributes[] & dynamicAttributes[] who have the same code.
  2. Find the size of array in RHS. If "code" is equal between the 2 lists ,the RHS list size will be 5.
  3. Now only for list size 5, I want to keep the dynamicAttributes[] by including "name" and "valueDescription" from attributes[].

But I was stuck on how to proceed from here.

[
  {
    "operation": "shift",
    "spec": {
      "attributes": {
        "*": {
          "@code": "@code",
          "@name": "@code",
          "@valueDescription": "@code"
        }
      },
      "result": {
        "dynamicAttributes": {
          "*": {
            "@value": "@code",
            "@active": "@code"
          }
        }
      }
    }
  },
  {
    "operation": "modify-overwrite-beta",
    "spec": {
      "*": "=size(@(1,&))"
    }
  }
]

Solution

  • I think your spec started on the right path by grouping fields from attributes and dynamicAttributes under a code value but you dont need to measure the size to determine what got merged. An easier approach would be grouping all field (keys and values) under the code value. When there is a match between the attributes and dynamicAttribute records, the code value will be an array of two similar codes. Using a second shift spec you can parse records where the code value has an element at index 1 which mean we got a merge therefor dump the entire code record into an array of result.dynamicAttributes[]. Finally , to set the code to a single code value we can use a third cardinality spec to select only one element from the code array. Here is the spec:

    [
      {
        "operation": "shift",
        "spec": {
          "attributes": {
            "*": {
              "code": "@(1,code).code",
              "*": "@(1,code).&"
            }
          },
          "result": {
            "dynamicAttributes": {
              "*": {
                "code": "@(1,code).code",
                "*": "@(1,code).&"
              }
            }
          }
        }
      }
      ,
      {
        "operation": "shift",
        "spec": {
          "*": {
            "code": {
              "1": {
                "@2": "result.dynamicAttributes[]"
              }
            }
          }
        }
        }
      ,
      {
        "operation": "cardinality",
        "spec": {
          "result": {
            "dynamicAttributes": {
              "*": {
                "code": "ONE"
              }
            }
          }
        }
      }
    ]