Search code examples
jolt

Jolt transformation String array


I am trying to transform an array of strings to an array of objects using jolt tranformation.

The case is that I want for every 4 elements the first mapped to a, second to b, third to c and fourth to d. Here is my array:

{
  "test": [
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8
  ]
}

My desired output is:

[
  {
    "a": 1,
    "b": 2,
    "c": 3,
    "d": 4
  },
  {
    "a": 5,
    "b": 6,
    "c": 7,
    "d": 8
  }
]

Is this possible with Jolt? I am trying to find an operation that is being triggered for every nth element of the list but nothing works.

I tried the @(0) but I am too far from what I want to achieve.


Solution

  • I think I got it figured out and it works for n size array where the size of the last array element after grouping can be 4 items or less. The trick here is how to break up those elements into the correct group.It turns out you can use the index of each item in the original array to help with that by getting the floor value of the index divided by 4 , For example the floor value of items with indexes 0-3 divided by 4 will be 0 , floor((4..7)/4) = 1 , floor((8..11)/4)=2 and so on. Once you know the group value for each element you can bucket each element into its group array , finally assign the letter to each element in each group array which will have total of 4 or less.

    [
      {
        //create an an object for each array element and add
        // index as new key\value. The index value will be used
        // in next transformation to get which array group each 
        // element will be part of
        "operation": "shift",
        "spec": {
          "test": {
            "*": {
              "@": "[&1].value",
              "$": "[&1].index"
            }
          }
        }
      },
      // To find which array group each element is
      // going to be part we use the floor function of the
      // division of the current index by 4.
      // Since Jolt doesnt have floor function, you
      // can do it by dividing by 4 and convert the result
      // to integer
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "*": {
            "divideBy4": "=divide(@(1,index),4)",
            "newArrayGroupIndex": "=toInteger(@(1,divideBy4))"
          }
        }
       },
      // Once we have defined the group index for each 
      // element, we can bucket each element into its group
      // array
      {
        "operation": "shift",
        "spec": {
          "*": {
            "newArrayGroupIndex": {
              "*": {
                "@(2,value)": "[&1]"
              }
            }
          }
        }
       },
      // finally since each group array will have 4 or less 
      // elements then we can use index 0-3 to assign the 
      // proper letter if index is found.
      {
        "operation": "shift",
        "spec": {
          "*": {
            "0": "[&1].a",
            "1": "[&1].b",
            "2": "[&1].c",
            "3": "[&1].d"
          }
        }
       }
    ]
    

    Not sure if this is the most efficient way. If someone has better solution please feel free to provide your input.

    Hope this helps. Thanks