skip to Main Content

I want to transform a JSON array using a JOLT specification.

My input:

[
  {
    "list": [ "item1" ]
  }
]

My desired output:

[
  {
    "list": [
      {
        "listType": "1",
        "listValue": "item1"
      }
    ]
  }
]

The goal is to transform every entry to a JSON object containing a type attribute.

This is my jolt spec so far:

[
  {
    "operation": "shift",
    "spec": {
      "*": {
        "list": {
          "*": {
            "#1": "[&3].&2[&1].listType",
            "@(0)": "[&3].&2[&1].listValue"
          }
        }
      }
    }
  }
]

And this works fine as long as the list is non-empty. However, if I pass an empty list "list": [] the attribute will be ignored in the transformed JSON. In this case, I would want to convert this to an empty list in my output as well, i.e. the desired transformation for this attribute would also be "list": [].

I found a couple of suggestions trying to achieve this with a default specification, but the thing is that I don’t want an empty list to be added if the attribute is not present in the original JSON. In this case, I don’t want to see this field in the output. I only want to see an empty list, if there was an empty list in the input in the first place.

Is this possible? I would also be happy with a solution that requires a null value instead of an empty list, i.e. "list": null would transform to "list": [] if this would be easier.

Edit: A few more examples of what I am trying to achieve:

Case 1:

[
  {
    "list": [
      "item1"
    ],
    "attribute2": "abc"
  }
]

should be transformed to

[
  {
    "list": [
      {
        "listType": "1",
        "listValue": "item1"
      }
    ],
    "attribute2": "abc"
  }
]

Case 2:

[
  {
    "list": [],
    "attribute2": "abc"
  }
]

should be transformed to

[
  {
    "list": [],
    "attribute2": "abc"
  }
]

Case 3

[
  {
    "attribute2": "abc"
  }
]

should be transformed to

[
  {
    "attribute2": "abc"
  }
]

Note: No list attribute in Case 3.

2

Answers


  1. You can separate the cases by using two objects labeled "list" and "*"(else case) in which the "list" array is replicated whenever the array is empty.

    If the array "list" is non-empty, then we pick the first component of the returning array through use of cardinality spec, deriving from the "list" object such as

    [
      {
        "operation": "shift",
        "spec": {
          "*": {
            "list": {
              "*": {
                "#1": "[&3].&2[&1][0].listType",
                "@(0)": "[&3].&2[&1][0].listValue"
              }
            },
            "*": {// else case
              "@1,list": "[&2].list[]",
              "@": "[&2].&"
            }
          }
        }
      },
      {
        "operation": "cardinality",
        "spec": {
          "*": {
            "list": "ONE"
          }
        }
      }
    ]
    
    Login or Signup to reply.
  2. You can use this spec:

    [
      {
        "operation": "shift",
        "spec": {
          "@": "aaa",
          "*": {
            "list": {
              "*": {
                "#1": "bbb[&3].&2[&1].listType",
                "@(0)": "bbb[&3].&2[&1].listValue"
              }
            },
            "*": "bbb[&1].&"
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "aaa": {
            "@": "ccc[]",
            "*": {
              "list": {
                "*": {
                  "@(5,bbb)": "ccc[]"
                }
              }
            }
          }
        }
      },
      {
        "operation": "modify-overwrite-beta",
        "spec": {
          "ccc": "=lastElement"
        }
      },
      {
        "operation": "shift",
        "spec": {
          "ccc": ""
        }
      }
    ]
    

    Input 1:

    [
      {
        "list": [
          "item1"
        ]
      }
    ]
    

    Output 1:

    [ {
      "list": [ {
        "listType": "1",
        "listValue": "item1"
      } ]
    } ]
    

    Input 2:

    [
      {
        "list": []
      }
    ]
    

    Output 2:

    [ {
      "list": []
    } ]
    

    Input 3:

    [
      {
        "list": null
      }
    ]
    

    Output 3:

    [ {
      "list": null
    } ]
    

    Input 4:

    [
      {}
    ]
    

    Output 4:

    [ {} ]
    

    Input 5:

    []
    

    Output 5:

    []
    

    First operation:

    First of all, we create a snapshot of all we have in the sample key like aaa. After that, we can loop through all of the input keys and transform them into the shape we want and finally save all of them into sample another key like bbb.

    Second operation:

    In this operation, we should merge all we have. so we can create a loop from our original input which means it is our snapshot or aaa key.

    Note 1: We save both aaa and bbb values in a ccc key. so they merged together.

    Note 2: If we have any issue with looping through list, we have just aaa‘s value. otherwise, we have a second index in the ccc. So always we can get the last element as a valid transformed output.

    Third operation:

    We can get the last element from the ccc array as a valid output.

    Fourth operation:

    We should bring the ccc value to one level up to achieve our desired output.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search