Mahesh Gopalan
Mahesh Gopalan

Reputation: 25

Jolt Spec transformation with nested Array structure

I have a json like

{
  "Product": [
    {
      "id": 123,
      "name": "foo",
      "ProductCharge": [
        {
          "productCode": "PIIB",
          "configLevel": "PROD",
          "feeRate": [
            {
              "rate": 123,
              "range": "123"
            },
            {
              "rate": 321,
              "range": "321"
            }
          ]
        }
      ]
    }
  ]
}

which I want transformed to this

{
  "Product" : [ {
    "id": 123,
      "name": "foo",
   // more fields
    "ProductCharge" : [ {
      "productCode" : "PIIB",
      "configLevel" : "PROD",
      "rate" : 123,
      "range" : "123"
    }, {
      "productCode" : "PIIB",
      "configLevel" : "PROD",
      "rate" : 321,
      "range" : "321"
    } ]
  } ]
}

I have this spec,

[
  {
    "operation": "shift",
    "spec": {
      "Product": {
        "*": {
          // Preserve the id, name, and any other top-level fields
          "ProductCharge": {
            "*": {
              "feeRate": {
                "*": {
                  "@2": { "*": "Product[#6].ProductCharge.[&1].&" },
                  "*": "Product[#6].ProductCharge.[&1].&"
                }
              }
            }
          }
        }
      }
    }
  },
  {
    "operation": "remove",
    "spec": {
      "Product": {
        "*": {
          "ProductCharge": {
            "*": {
              "feeRate": ""
            }
          }
        }
      }
    }
  }
]

My current spec is missing the "id" and "name" and the other fields under "Product". If I try to add this line to get the remaining fields under "Product", it distorts the whole structure

"*": "Product[#2].&"

Can someone point out how to get around this.

Edit:

Barbaros's your solution worked, but I realized when I have more than one ProductCharge like below

{
  "Product": [
    {
      "id": 123,
      "name": "foo",
      "ProductCharge": [
        {
          "aboveAmount": 0,
          "chargeType": "ABC",
          "chargeValueType": "PERCENT",
          "frequency": 1,
          "feeRate": [
            {
              "bandNumber": 1,
              "rate": 0.6
            },
            {
              "bandNumber": 2,
              "rate": 1.7
            }
          ]
        },
        {
          "aboveAmount": 0,
          "chargeType": "DEF",
          "chargeValueType": "PERCENT",
          "frequency": 1,
          "feeRate": [
            {
              "bandNumber": 1,
              "rate": 0.75
            },
            {
              "bandNumber": 2,
              "rate": -0.55
            }
          ]
        }
      ]
    }
  ]
}

rather than create it as 4 separate sections

{
  "Product" : [ {
    "id" : 123,
    "name" : "foo",
    "ProductCharge" : [ {
      "aboveAmount" : 0,
      "chargeType" : "ABC",
      "chargeValueType" : "PERCENT",
      "frequency" : 1,
      "bandNumber" : 1,
      "rate" : 0.6
    }, {
      "aboveAmount" : 0,
      "chargeType" : "ABC",
      "chargeValueType" : "PERCENT",
      "frequency" : 1,
      "bandNumber" : 2,
      "rate" : 1.7
    }, {
      "aboveAmount" : 0,
      "chargeType" : "DEF",
      "chargeValueType" : "PERCENT",
      "frequency" : 1,
      "bandNumber" : 1,
      "rate" : 0.75
    }, {
      "aboveAmount" : 0,
      "chargeType" : "DEF",
      "chargeValueType" : "PERCENT",
      "frequency" : 1,
      "bandNumber" : 2,
      "rate" : -0.55
    } ]
  } ]
}

it creates like this;

{
  "Product" : [ {
    "id" : 123,
    "name" : "foo",
    "ProductCharge" : [ {
      "aboveAmount" : [ 0, 0 ],
      "chargeType" : [ "ABC", "DEF" ],
      "chargeValueType" : [ "PERCENT", "PERCENT" ],
      "frequency" : [ 1, 1 ],
      "bandNumber" : [ 1, 1 ],
      "rate" : [ 0.6, 0.75 ]
    }, {
      "aboveAmount" : [ 0, 0 ],
      "chargeType" : [ "ABC", "DEF" ],
      "chargeValueType" : [ "PERCENT", "PERCENT" ],
      "frequency" : [ 1, 1 ],
      "bandNumber" : [ 2, 2 ],
      "rate" : [ 1.7, -0.55 ]
    } ]
  } ]
}

Upvotes: 2

Views: 85

Answers (1)

Barbaros Özhan
Barbaros Özhan

Reputation: 65408

You can handle the issue better by accumulating the inner stuff( those within the "feeRate" array ) in a new object, namely "Others" while using placeholder ampersand symbols for the keys such as "Product", "ProductCharge" and "feeRate" such that

[
  {
    "operation": "shift",
    "spec": {
      "Product": {
        "*": {
          "*": "&2[&1].&",
          "ProductCharge": {
            "*": {
              "*": "&4[&3].&2[&1].Others.&",
              "feeRate": "&4[&3].&2[&1].&"
            }
          }
        }
      }
    }
  },
  {
    "operation": "shift",
    "spec": {
      "Product": {
        "*": {
          "*": "&2[&1].&",
          "ProductCharge": {
            "*": {
              "feeRate": {
                "*": {
                  "@2,Others": { "*": "&7[&6].&5[&1].&" },
                  "*": "&6[&5].&4[&1].&"
                }
              }
            }
          }
        }
      }
    }
  }
]

the demo on the site Jolt Transform Demo Using v0.1.1 is :

enter image description here

Edit : You'll need to add one more partition for this new case and the expression &3_&1 will do the trick such as

[
  {
    "operation": "shift",
    "spec": {
      "Product": {
        "*": {
          "*": "&2.&",
          "ProductCharge": {
            "0": { //in order to bring only once among duplicated values
              "*": "&4.&2.Others.&",
              "feeRate": {
                "*": {
                  "*": "&6.&4.&2.&3_&1.&"
                }
              }
            },
            "*": {
              "feeRate": {
                "*": {
                  "*": "&6.&4.&2.&3_&1.&"
                }
              }
            }
          }
        }
      }
    }
  },
  {
    "operation": "shift",
    "spec": {
      "Product": {
        "*": "&1[0].&",
        "ProductCharge": {
          "feeRate": {
            "*": {
              "@": "&4[0].&3.[#2]",
              "@2,Others": { "*": "&5[0].&4.[#3].&" }
            }
          }
        }
      }
    }
  }
]

This last spec will handle the previous case as well

Upvotes: 1

Related Questions