Search code examples
jsonjolt

Transpose an array to another one with Jolt


I have tried hard to transpose the input json string to another one with Jolt as follows. But I couldn't write the correct Jolt Spec to achieve the transformation, can Jolt do something like this? Thanks!

Input:

{
  "result": [
    {
      "name": "AAA",
      "value1": "AAA-111",
      "value2": "AAA-222",
      "value3": "AAA-333"
    },
    {
      "name": "BBB",
      "value1": "BBB-111",
      "value2": "BBB-222",
      "value3": "BBB-333"
    },
    {
      "name": "CCC",
      "value1": "CCC-111",
      "value2": "CCC-222",
      "value3": "CCC-333"
    }
  ]
}

Expected output:

{
  "result": [
    {
      "value_name":"value1",
      "AAA":"AAA-111",
      "BBB":"BBB-111",
      "CCC":"CCC-111"
    },
    {
      "value_name":"value2",
      "AAA":"AAA-222",
      "BBB":"BBB-222",
      "CCC":"CCC-222"
    },
    {
      "value_name":"value3",
      "AAA":"AAA-333",
      "BBB":"BBB-333",
      "CCC":"CCC-333"
    }
  ]
}

Solution

  • This is not just "Transpose an array to another one".

    There are actually 4 things going on here:

    1. Pivot/group the incoming data into "value1", "value2", "value3"
    2. Extract a new key "AAA" from the that that is assumed to be hyphen delimited. Aka build "AAA" : "AAA-111".
    3. Get "value1", "value2" etc to be a value of "value_name" and not a key in the json.
    4. Build an output array given the number of "value1/2/3" items seen, not the number of elements in the incoming array. E.g. if your three input items did not have "value3" defined at all, then your final output "result" array would only have two array elements; one for "value1" and one for "value2".

    This spec works, but given how much is going on may be fragile wrt weird input.

    To understand what this is doing I recommend opening up 4 browser tabs of the jolt-demo site, running each shift operation by itself, copying the output of one tab into the input of the next tab.

    That is effectively how I wrote this.

    Spec

    [
      {
        "operation": "shift",
        "spec": {
          "result": {
            "*": {
              // first group all the data by valueKEY
              "value*": "&[]"
            }
          }
        }
      },
      {
        // next build the 'AAA':'AAA-111' structure
        //  but not yet in the final result array
        "operation": "shift",
        "spec": {
          "value*": { // should be value1, value2, etc
            "*": { // array index
              "*-*": {
                // keep top level value1, value2
                // but now build the 'AAA':'AAA-111' logic
                // This is assuming that it is hypen "-" delimited
                "@1": "&3.&(1,1)"
              }
            }
          }
        }
      },
      {
        // now build 'value_name':'value1'
        "operation": "shift",
        "spec": {
          "value*": {
            // pass thru the "AAA':'AAA-111' data 
            "*": "&1.&",
            //
            // push value name down to be siblings of 'AAA':'AAA-111'
            "$": "&1.value_name"
          }
        }
      },
      {
        // finally now that the core data is all setup, accumulate 
        //  into an array
        "operation": "shift",
        "spec": {
          "value*": "result[]"
        }
      }
    ]