Search code examples
jsonapache-nifijolt

Convert a array of objects to array using jolt


I am trying to convert the given input.json to the expected output.json I have successfully converted that address into a string but failed at converting the hobbies array into the desired output.

I have tried different ways like using $ wildcard to change the key name to name but it didn't work.I have also used @ wildcard to change the name of the object from index to some name but it also didn't work

Input.json

{
  "users": [
    {
      "name": "John Doe",
      "age": 35,
      "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip": "12345"
      },
      "hobbies": [
        {
          "name": "reading",
          "type": "indoor"
        },
        {
          "name": "hiking",
          "type": "outdoor"
        }
      ]
    },
    {
      "name": "Jane Doe",
      "age": 30,
      "address": {
        "street": "456 First St",
        "city": "Othertown",
        "state": "NY",
        "zip": "67890"
      },
      "hobbies": [
        {
          "name": "swimming",
          "type": "outdoor"
        },
        {
          "name": "painting",
          "type": "indoor"
        }
      ]
    }
  ]
}

Expected Output.json

[  {  
    "Name": "John Doe",
    "Address": "123 Main St, Anytown, CA 12345", 
    "Hobbies": [ "reading", "hiking" ]
  },
  {
    "Name": "Jane Doe",
    "Address": "456 First St, Othertown, NY 67890",
    "Hobbies": [
      "swimming",
      "painting"
    ]
  }
]

Solution

  • You can consecutively use shift and modify transformation specs such as

    [
      { // form "Address" and "Hobbies" arrays
        "operation": "shift",
        "spec": {
          "users": {
            "*": {
              "name": "[#2].Name",
              "ad*": {
                "*": "[#3].ad1",//grab 1st asterisk replacement(might be multiple) after going 1 level up the tree 
                "state|zip": "[#3].ad2"
              },
              "h*": {
                "*": {
                  "n*": "[#4].H&(2,1)"//grab 1st asterisk replacement after going 2 level up the tree
                }
              }
            }
          }
        }
      },
      { // concatenate the components of the "Address" array 
        "operation": "modify-overwrite-beta",
        "spec": {
          "*": {
            "ad1": "=join(', ',@(1,&))",
            "ad2": "=join(' ',@(1,&))",
            "Adress": "=concat(@(1,ad1),', ',@(1,ad2))"
          }
        }
      },
      { // get rid of extra auxiliary attributes
        "operation": "remove",
        "spec": {
          "*": {
            "ad*": ""
          }
        }
      }
    ]
    

    Edit : Possible directly to use concat function as follows as you've already mentioned in the comment section :

    [
      { 
        "operation": "shift",
        "spec": {
          "users": {
            "*": {
              "name": "[#2].Name",
              "ad*": {
                "*": "[#3].&"
              },
              "h*": {
                "*": {
                  "n*": "[#4].H&(2,1)"
                }
              }
            }
          }
        }
      },
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "*": {
            "Address": "=concat(@(1,street),', ',@(1,city),', ',@(1,state),' ',@(1,zip))"
          }
        }
      },
      {
        "operation": "remove",
        "spec": {
          "*": {
            "*t*|z*": ""
          }
        }
      }
    ]
    

    but principally I'd prefer using join rather than concat as much as possible as join handles all in once.