Search code examples
jsonjolt

Json object is getting created in a seperate tag for jolt transformation


I am trying below to convert from single object to array but it is creating in seperate tag. Tried with multiple combinations but not getting in same tag

{
  "payload": {
    "settings": [
      {
        "account": [
          {
            "number": "1",
            "purpose": {
              "type": "netflix"
            }
          }
        ]
      }
    ]
  }
}

my jolt spec is as below

[
  {
    "operation": "shift",
    "spec": {
      "payload": {
        "*": "&1.&",
        "settings": {
          "*": {
            "*": "&3.&2.[&1].&",
            "account": {
              "*": {
                "*": "&5.&4.[&3].&2.[&1].&",
                "purpose": {
                  "0": {
                    "@(2,purpose)": "&4.[&3].&2"
                  },
                  "type": {
                    "@(2,purpose)": "&4.[&3].&2[]"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
]

Output coming as this

{
  "payload": {
    "settings": [
      {
        "account": [
          {
            "number": "1"
          }
        ]
      }
    ]
  },
  "account": [
    {
      "purpose": [
        {
          "type": "netflix"
        }
      ]
    }
  ]
}   

where as expected output should be like below

{
  "payload": {
    "settings": [
      {
        "account": [
          {
            "number": "1",
            "purpose": [
              {
                "type": "netflix"
              }
            ]
          }
        ]
      }
    ]
  }
}   

Can please let me know what is the wrong I am doing in the spec.


Solution

  • What you need is to add square brackets ([]) to the inner most object within the common nested curly braces of an object in a shift transformation spec such as

    [
      {
        "operation": "shift",
        "spec": {
          "payload": {
            "settings": {
              "*": {
                "account": {
                  "*": {
                    "*": "&5.&4[&3].&2[&1].&", // the elements other than "purpose"
                    "purpose": {
                      "@": "&6.&5[&4].&3[&2].&1[]" // +1 level deeper than the other elements
                    }
                  }
                }
              }
            }
          }
        }
      }
    ]
    

    Edit : If you need to return the same expected output for both type of inputs in which the purpose is a key of an object ( "purpose": { "type": "netflix" } ) as already exists within the original input or that is a key of an array of an object ( "purpose": [{ "type": "netflix" }] ) as stated in the latest comment, then you might use the following spec :

    [
      {
        "operation": "shift",
        "spec": {
          "payload": {
            "settings": {
              "*": {
                "account": {
                  "*": {
                    "*": "&5.&4[&3].&2[&1].&",
                    "purpose": {
                      "*": {
                        "@1": "&7.&6[&5].&4[&3].&2[]" //this will return whenever "purpose" is an object only
                      },
                      "0": {
                        "@1": "&7.&6[&5].&4[&3].&2" //this will return whenever "purpose" has 
                                                    //an array wrapper which nests the object inside
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    ]
    

    Btw, you should fix the question so as to include that extra criteria as well.