Search code examples
jsonapache-nifijolt

Convert Flatten Json into array of json using JOLT


I need to use Jolt to transform a flat JSON object into an array of JSON objects, where each row in the array corresponds to a unique index number from the original object. The output should have as many rows as there were index numbers in the original object.

Input JSON 1

{
  "id": "0001",
  "type": "donut",
  "name": "Cake",
  "ppu": 0.55,
  "batters.location": "test",
  "batters.batter[0].id": "1001",
  "batters.batter[0].type": "Regular",
  "batters.batter[1].id": "1002",
  "batters.batter[1].type": "Chocolate"
}

Output JSON 1

[
  {
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters.location": "test",
    "batters.batter.id": "1001",
    "batters.batter.type": "Regular"
  },
  {
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters.location": "test",
    "batters.batter.id": "1002",
    "batters.batter.type": "Chocolate"
  }
]

Another example like

Input JSON 2

{
  "[0].id": "0001",
  "[0].type": "donut",
  "[0].name": "Cake",
  "[0].ppu": 0.55,
  "[0].batters.location": "test",
  "[0].batters.batter[0].id": "1001",
  "[0].batters.batter[0].type": "Regular",
  "[0].batters.batter[1].id": "1002",
  "[0].batters.batter[1].type": "Chocolate",
  "[1].id": "0002",
  "[1].type": "donut",
  "[1].name": "Cake2",
  "[1].ppu": 0.75,
  "[1].batters.location": "test2",
  "[1].batters.batter[0].id": "1002",
  "[1].batters.batter[0].type": "Regular",
  "[1].batters.batter[1].id": "1003",
  "[1].batters.batter[1].type": "Chocolate"
}

Output JSON 2

[
  {
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters.location": "test",
    "batters.batter.id": "1001",
    "batters.batter.type": "Regular"
  },
  {
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters.location": "test",
    "batters.batter.id": "1002",
    "batters.batter.type": "Chocolate"
  },
  {
    "id": "0002",
    "type": "donut",
    "name": "Cake2",
    "ppu": 0.75,
    "batters.location": "test2",
    "batters.batter.id": "1002",
    "batters.batter.type": "Regular"
  },
  {
    "id": "0002",
    "type": "donut",
    "name": "Cake2",
    "ppu": 0.75,
    "batters.location": "test2",
    "batters.batter.id": "1003",
    "batters.batter.type": "Chocolate"
  }
]

Solution

  • You can achieve your both desired outputs with this single JOLT spec:

    [
      {
        "operation": "shift",
        "spec": {
          "\\[*\\].*\\[*\\].*": {
            "@(1,\\[&(0,1)\\]\\.id)": "[&(1,1)][&(1,3)].id",
            "@(1,\\[&(0,1)\\]\\.type)": "[&(1,1)][&(1,3)].type",
            "@(1,\\[&(0,1)\\]\\.name)": "[&(1,1)][&(1,3)].name",
            "@(1,\\[&(0,1)\\]\\.ppu)": "[&(1,1)][&(1,3)].ppu",
            "@(1,\\[&(0,1)\\]\\.batters\\.location)": "[&(1,1)][&(1,3)].batters\\.location",
            "@": "[&(1,1)][&(1,3)].&(1,2)\\.&(1,4)"
          },
          "*\\[*\\].*": {
            "@(1,id)": "[0][&(1,2)].id",
            "@(1,type)": "[0][&(1,2)].type",
            "@(1,name)": "[0][&(1,2)].name",
            "@(1,ppu)": "[0][&(1,2)].ppu",
            "@(1,batters\\.location)": "[0][&(1,2)].batters\\.location",
            "@": "[0][&(1,2)].&(1,1)\\.&(1,3)"
          }
        }
      },
      {
        "operation": "cardinality",
        "spec": {
          "*": {
            "*": {
              "*": "ONE"
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": ""
          }
        }
      }
    ]