Home > Software design >  change name of property in a list to list nested json using JOLT
change name of property in a list to list nested json using JOLT

Time:12-08

I am news to jolt json transformation. So looking for help in transforming nested json having list of values to nested json with list as following.

Input json

{
  "userData": [
    {
      "userId": "1",
      "age": "20",
      "firstName": "firstname1",
      "lastname": "lastname1",
      "zipCode": "zipcode1",
      "street": "street1",
      "city": "city1",
      "country": "country",
      "gender": "gender1",
      "grade": "grade1",
      "birthday": "birthday1"
    },
    {
      "userId": "2",
      "age": "25",
      "firstName": "firstname2",
      "lastname": "lastname2",
      "zipCode": "zipcode2",
      "street": "street2",
      "city": "city2",
      "country": "country2",
      "gender": "gender2",
      "grade": "grade2",
      "birthday": "birthday2"
    }
  ]
}

Jolt Specification

[
  {
    "operation": "shift",
    "spec": {
      "userData": {
        "*": {
          "userId": "data.[&1].ID",
          "*": "data.[&1].&",
          "zipCode": {
            "#custom-field1": "adr_&1.property",
            "@": "adr_&.value"
          },
          "street": {
            "#custom-field2": "adr_&1.property",
            "@": "adr_&.value"
          },
          "city": {
            "#custom-field3": "adr_&1.property",
            "@": "adr_&.value"
          },
          "country": {
            "#custom-field4": "adr_&1.property",
            "@": "adr_&.value"
          }
        }
      }
    }
  }
]

Output

{
  "data" : [ {
    "ID" : "1",
    "age" : "20",
    "firstName" : "firstname1",
    "lastname" : "lastname1",
    "gender" : "gender1",
    "grade" : "grade1",
    "birthday" : "birthday1"
  }, {
    "ID" : "2",
    "age" : "25",
    "firstName" : "firstname2",
    "lastname" : "lastname2",
    "gender" : "gender2",
    "grade" : "grade2",
    "birthday" : "birthday2"
  } ],
  "adr_zipCode" : {
    "property" : [ "custom-field1", "custom-field1" ],
    "value" : [ "zipcode1", "zipcode2" ]
  },
  "adr_street" : {
    "property" : [ "custom-field2", "custom-field2" ],
    "value" : [ "street1", "street2" ]
  },
  "adr_city" : {
    "property" : [ "custom-field3", "custom-field3" ],
    "value" : [ "city1", "city2" ]
  },
  "adr_country" : {
    "property" : [ "custom-field4", "custom-field4" ],
    "value" : [ "country", "country2" ]
  }
}

Expected json

{
  "data": [
    {
      "ID": "1",
      "age": "20",
      "firstName": "firstname1",
      "lastname": "lastname1",
      "gender": "gender1",
      "grade": "grade1",
      "birthday": "birthday1",
      "address": [
        {
          "property": "custom-field1",
          "value": "zipcode1"
        },
        {
          "property": "custom-field2",
          "value": "street1"
        },
        {
          "property": "custom-field3",
          "value": "city1"
        },
        {
          "property": "custom-field4",
          "value": "country"
        }
      ]
    },
    {
      "ID": "2",
      "age": "25",
      "firstName": "firstname2",
      "lastname": "lastname2",
      "gender": "gender2",
      "grade": "grade2",
      "birthday": "birthday2",
      "address": [
        {
          "property": "custom-field1",
          "value": "zipcode2"
        },
        {
          "property": "custom-field2",
          "value": "street2"
        },
        {
          "property": "custom-field3",
          "value": "city2"
        },
        {
          "property": "custom-field4",
          "value": "country2"
        }
      ]
    }
  ]
}

CodePudding user response:

You can use individual value arrays of their indexes to be used within the upcoming specs with a tricky zeroth member which will be removed later, after been used such as

[
  {
    "operation": "shift",
    "spec": {
      "userData": {
        "*": {
          "userId": "data[&1].ID",
          "@(0,age)": "data[&1].age", //multiplexed this attribute in order to make it the zeroth index, which will be removed within the upcoming specs, for the "address" array at the same time, as indexing starts from zero ...
          "*": "data[&1].&",
          "a*|z*|s*|c*": {//separating "zipCode", "street", "city", "country" attributes from the others while using "a*" for "age" is tricky, temporarily
            "@": "data[&2].value"
          }
        }
      }
    }
  },
  {
    "operation": "shift",
    "spec": {
      "data": {
        "*": {
          "*": "&2[&1].&",
          "value": {
            "*": {
              "#property": "&4[&3].address[&1].custom-field&1",
              "@(2,value[&])": "&4[&3].address[&1].value"
            }
          }
        }
      }
    }
  },
  { // the attributes are written individually to keep the desired sorting
    "operation": "shift",
    "spec": {
      "data": {
        "*": {
          "ID": "&2[&1].&",
          "age": "&2[&1].&",
          "firstName": "&2[&1].&",
          "lastname": "&2[&1].&",
          "gender": "&2[&1].&",
          "grade": "&2[&1].&",
          "birthday": "&2[&1].&",
          "address": {
            "0": "&4[&3].&2[&1]",
            "*": {
              "*": {
                "$": "&5[&4].&3[&2].@(0)" // key-value pairs are exchanged for this attribute
              },
              "value": "&4[&3].&2[&1].&"
            }
          }
        }
      }
    }
  },
  { // get rid of null components of the array
    "operation": "modify-overwrite-beta",
    "spec": {
      "*": "=recursivelySquashNulls"
    }
  }
]

CodePudding user response:

enter image description here

[
    {
        "operation": "shift",
        "spec": {
            "userData": {
                "*": {
                    "userId": "data.[&1].ID",
                    "*": "data.[&1].&",
                    "zipCode": {
                        "#custom-field1": "data[#3].address[#2].property",
                        "@": "data[#3].address[#2].value"
                    },
                    "street": {
                        "#custom-field2": "data[#3].address[#2].property",
                        "@": "data[#3].address[#2].value"
                    },
                    "city": {
                        "#custom-field3": "data[#3].address[#2].property",
                        "@": "data[#3].address[#2].value"
                    },
                    "country": {
                        "#custom-field4": "data[#3].address[#2].property",
                        "@": "data[#3].address[#2].value"
                    }
                }
            }
        }
    },
    { // get rid of null components of the array
        "operation": "modify-overwrite-beta",
        "spec": {
            "*": "=recursivelySquashNulls"
        }
    }
]

CodePudding user response:

You may consider another library Josson to do the same job by shorter transformation statement.

https://github.com/octomix/josson

Deserialization

Josson josson = Josson.fromJsonString(
    "{"  
    "  \"userData\": ["  
    "    {"  
    "      \"userId\": \"1\","  
    "      \"age\": \"20\","  
    "      \"firstName\": \"firstname1\","  
    "      \"lastname\": \"lastname1\","  
    "      \"zipCode\": \"zipcode1\","  
    "      \"street\": \"street1\","  
    "      \"city\": \"city1\","  
    "      \"country\": \"country\","  
    "      \"gender\": \"gender1\","  
    "      \"grade\": \"grade1\","  
    "      \"birthday\": \"birthday1\""  
    "    },"  
    "    {"  
    "      \"userId\": \"2\","  
    "      \"age\": \"25\","  
    "      \"firstName\": \"firstname2\","  
    "      \"lastname\": \"lastname2\","  
    "      \"zipCode\": \"zipcode2\","  
    "      \"street\": \"street2\","  
    "      \"city\": \"city2\","  
    "      \"country\": \"country2\","  
    "      \"gender\": \"gender2\","  
    "      \"grade\": \"grade2\","  
    "      \"birthday\": \"birthday2\""  
    "    }"  
    "  ]"  
    "}");

Transformation

JsonNode node = josson.getNode(
    "map(data:userData"  
    "      .field(ID:userId, userId:,"  
    "             zipCode:, street:, city:, country:,"  
    "             address:collect("  
    "               map(property:'customer-field1',value:zipCode),"  
    "               map(property:'customer-field2',value:street),"  
    "               map(property:'customer-field3',value:city),"  
    "               map(property:'customer-field4',value:country))))");
System.out.print(node.toPrettyString());

Output

{
  "data" : [ {
    "age" : "20",
    "firstName" : "firstname1",
    "lastname" : "lastname1",
    "gender" : "gender1",
    "grade" : "grade1",
    "birthday" : "birthday1",
    "ID" : "1",
    "address" : [ {
      "property" : "customer-field1",
      "value" : "zipcode1"
    }, {
      "property" : "customer-field2",
      "value" : "street1"
    }, {
      "property" : "customer-field3",
      "value" : "city1"
    }, {
      "property" : "customer-field4",
      "value" : "country"
    } ]
  }, {
    "age" : "25",
    "firstName" : "firstname2",
    "lastname" : "lastname2",
    "gender" : "gender2",
    "grade" : "grade2",
    "birthday" : "birthday2",
    "ID" : "2",
    "address" : [ {
      "property" : "customer-field1",
      "value" : "zipcode2"
    }, {
      "property" : "customer-field2",
      "value" : "street2"
    }, {
      "property" : "customer-field3",
      "value" : "city2"
    }, {
      "property" : "customer-field4",
      "value" : "country2"
    } ]
  } ]
}
  • Related