Search code examples
javajsonjolt

How to write JOLT transformation that modifies a specific object in an array based on internal field?


What I would like to be able to do is target a specific "value" field that corresponds to "name" = "Special Value" and modify it with a String operation (e.g. toUpper()) without modifying any other objects/fields.

Here is my input JSON:

{
  "a": "aa",
  "b": "bb",
  "attributes": [
    {
      "groupName": "Group 1",
      "attribute": [
        {
          "name": "c",
          "value": "cc"
        }
      ]
    },
    {
      "groupName": "Group 2",
      "attribute": [
        {
          "name": "e",
          "value": "ee"
        },
        {
          "name": "Special Value",
          "value": "hello"
        },
        {
          "name": "f",
          "value": "ff"
        }
      ]
    }
  ]
}

This is my desired output JSON:

{
  "a": "aa",
  "b": "bb",
  "attributes": [
    {
      "groupName": "Group 1",
      "attribute": [
        {
          "name": "c",
          "value": "cc"
        }
      ]
    },
    {
      "groupName": "Group 2",
      "attribute": [
        {
          "name": "e",
          "value": "ee"
        },
        {
          "name": "Special Value",
          "value": "HELLO"
        },
        {
          "name": "f",
          "value": "ff"
        }
      ]
    }
  ]
}

I have figured out how to target the correct field using the shift operation:

Spec:

[
  {
    "operation": "shift",
    "spec": {
      "attributes": {
        "*": {
          "attribute": {
            "*": {
              "name": {
                "Special Value": {
                  "@(2,value)": "test"
                }
              }
            }
          }
        }
      }
    }
  }
]

Output:

{
  "test" : "hello"
}

However, I can't use this same spec with the modify-overwrite-beta operation without getting an error. How can I write a spec to perform a String operation on this specific field?


Solution

  • An option might be changing the related sub-indexes, which will be keys of the sub-objects of those arrays respectively, by adding an extra character(such as an underscore) within a shift transformation spec, while using conditional logic, and then use that function( toUpper ) within the upcoming modify spec as in the following transformation :

    [
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "attributes": {
            "*": {
              "*": "&2.&1.&",
              "attribute": {
                "*": {
                  "name": {
                    "Special Value": {
                      "@2,name": "&6.&5.&4.&3_.name",
                      "@2,value": "&6.&5.&4.&3_.value"
                    },
                    "*": {
                      "@2,name": "&6.&5.&4.&3.name",
                      "@2,value": "&6.&5.&4.&3.value"
                    }
                  }
                }
              }
            }
          }
        }
      },
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "attributes": {
            "*": {
              "attribute": {
                "*_": {
                  "value": "=toUpper(@(1,&))"
                }
              }
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": "&",
          "attributes": {
            "*": {
              "*": "&2[&1].&",
              "attribute": {
                "*": {
                  "*": "&4[&3].&2[#2].&"
                }
              }
            }
          }
        }
      }
    ]