jsonjolt

Assign Missing acceptId Using acceptIds List in JOLT Transformation


I have a JSON input where:

  1. acceptIds is an array containing some IDs.
  2. phoneNumbers is an array of objects.
  3. Some objects inside phoneNumbers contain an accept object but are missing the acceptId field.
  4. The number of IDs in acceptIds is always equal to the number of accept objects missing acceptId.

I need a JOLT transformation to assign values from acceptIds to acceptId only where it is missing, while keeping the rest of the structure unchanged.

Example Input:

{
  "acceptIds": [
    "23"
  ],
  "phoneNumbers": [
    {
      "phoneNumber": "123",
      "accept": {
        "acceptId": "1",
        "acceptName": "phone"
      }
    },
    {
      "phoneNumber": "456"
    },
    {
      "phoneNumber": "789",
      "accept": {
        "acceptName": "phone"
      }
    }
  ]
}

Expected Output:

{
  "phoneNumbers": [
    {
      "phoneNumber": "123",
      "accept": {
        "acceptId": "1",
        "acceptName": "phone"
      }
    },
    {
      "phoneNumber": "456"
    },
    {
      "phoneNumber": "789",
      "accept": {
        "acceptId": "23",
        "acceptName": "phone"
      }
    }
  ]
}

Requirements:

acceptIds should only be used for objects where accept.acceptId is missing. The order of acceptIds should be maintained while filling the missing values. If an object does not have an accept object, it should remain unchanged. How can I achieve this using JOLT transformation?


Solution

  • You can use the following transformation spec :

    [
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "phoneNumbers": {
            "*": {
              "accept?": { //check if "accept" object exists
                "~acceptId": "NOacceptIds" //create a new attribute as "acceptId": "NOacceptIds" if "acceptId" does not exist
              }
            }
          }
        }
      },
      {//create two independent arrays "acceptId" and "NOacceptIds"
        "operation": "shift",
        "spec": {
          "*s": "arr.&(0,1)",//0 represents the current level 1 represents the 1st asterisk
                             //in order to extract the substring "acceptId"
          "phoneNumbers": {
            "*": {
              "*": "&1.&",
              "accept": {
                "acceptId": {
                  "NOacceptIds": { "$3": "arr.&1" },
                  "*": { "@1": "&4.&2" }
                },
                "*": "&2.&"
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": "&1.&",
            "acc*": "&1.accept.&"
          },
          "arr": {//match the newly formed arrays to fill the value(s) for the missing attribute(s) 
            "*Id": {
              "*": "@(2,NOacceptIds[&]).&(1,1).&1"
            }
          }
        }
      },
      { //keep the original object order within the "phoneNumbers" array
        "operation": "sort"
      },
      {//nest the whole content under this key 
        "operation": "shift",
        "spec": {
          "*": "phoneNumbers[]"
        }
      }
    ]