Search code examples
jsontransformationjolt

Jolt spec to combine different attributes


I'm trying to move the key to the value of another JSON key. The destination value is an array, and I'm attempting to add an element to that array.

Case 1: Input json object:

{
  "Name": {
    "PRI": {
      "firstName": "Joe"
    }
  },
  "Ids": {
    "IND": {
      "IND-ADR": {
        "id": "ind-adr-id",
        "key": "ind1"
      },
      "IND-PAN": {
        "id": "ind-pan-id",
        "key": "ind2"
      }
    },
    "USA": {
      "USA-SSN": {
        "id": "usa-ssn-id",
        "key": "usa1"
      }
    }
  },
  "OtherIds": {
    "1970-01-01": {
      "0": {
        "idLast": "2023"
      }
    }
  }
}

Case 2: Input json object:

{
  "Name": {
    "PRI": {
      "firstName": "Joe"
    }
  },
  "OtherIds": {
    "1970-01-01": {
      "0": {
        "idLast": "2023"
      }
    }
  }
}

The output I'm expecting is something like this: Case 1 expected output:

{
  "Name" : {
    "PRI" : {
      "firstName" : "Joe"
    }
  },
  "Ids" : [ {
    "country" : "IND",
    "IdType" : "IND-ADR",
    "id" : "ind-adr-id",
    "key" : "ind1"
  }, {
    "country" : "IND",
    "IdType" : "IND-PAN",
    "id" : "ind-pan-id",
    "key" : "ind2"
  }, {
    "country" : "USA",
    "IdType" : "USA-SSN",
    "id" : "usa-ssn-id",
    "key" : "usa1"
  }, { //from OtherIds
    "country" : "USA", // hard-coding this
    "IdType" : "SSN Tail", //hard-coding this
    "idLast" : "2023"
  } ]
}

Case 2 expected output:

{
  "Name" : {
    "PRI" : {
      "firstName" : "Joe"
    }
  },
  "Ids" : [ {//from OtherIds
    "country" : "USA", // hard-coding this
    "IdType" : "SSN Tail", //hard-coding this
    "idLast" : "2023"
  } ]
}

My current JOLT spec:

[
  {
    "operation": "shift",
    "spec": {
      "Ids": {
        "*": {
          "*": {
            "$1": "NID.&2_&1.&3.country",
            "$": "NID.&2_&1.&3.IdType",
            "*": "NID.&2_&1.&3.&"
          }
        }
      },
      "*": "&"
    }
  },
  {
    "operation": "shift",
    "spec": {
      "NID": {
        "*": {
          "*": {
            "*": "&1[#3].&"
          }
        }
      },
      "*": "&"
    }
  }
]

My current output:

{
  "Name" : {
    "PRI" : {
      "firstName" : "Joe"
    }
  },
  "Ids" : [ {
    "country" : "IND",
    "IdType" : "IND-ADR",
    "id" : "ind-adr-id",
    "key" : "ind1"
  }, {
    "country" : "IND",
    "IdType" : "IND-PAN",
    "id" : "ind-pan-id",
    "key" : "ind2"
  }, {
    "country" : "USA",
    "IdType" : "USA-SSN",
    "id" : "usa-ssn-id",
    "key" : "usa1"
  } ],
  "OtherIds" : {
    "1970-01-01" : {
      "0" : {
        "idLast" : "2023"
      }
    }
  }
}

Is it possible to modify my current jolt spec to cover both cases mentioned above?


Solution

  • You could separately pick the objects with key "Ids" vs. "OtherIds" within the first spec while extracting the literals "Ids" to be used within the second one which will contain # operator on the left hand side to hardcode the desired literal such as

    [
      {
        "operation": "shift",
        "spec": {
          "*": { // else case, eg. Ids
            "*": {
              "*": {
                "$1": "&2_&1.&3.country",
                "$": "&2_&1.&3.IdType",
                "*": "&2_&1.&3.&"
              }
            }
          },
          "Other*": {
            "*": {
              "*": {
                "#USA": "&2_&1.&(3,1).country", // bring the value of the asterisk within "Other*", eg. Ids
                "#SSN Tail": "&2_&1.&(3,1).IdType",
                "*": "&2_&1.&(3,1).&"
              }
            }
          },
          "Name": "&"
        }
      },
      {
        "operation": "shift",
        "spec": {
          "Name": "&",
          "*": {
            "*": "&[]" // keep square brackets considering the cases similar to the second one
          }
        }
      }
    ]
    

    which is common transformation for both of the inputs.