Prasad S Deshpande
Prasad S Deshpande

Reputation: 1412

change name of property in a list to list nested json using JOLT

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"
        }
      ]
    }
  ]
}

Upvotes: 0

Views: 198

Answers (3)

Raymond Choi
Raymond Choi

Reputation: 1273

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"
    } ]
  } ]
}

Upvotes: 0

Prasad S Deshpande
Prasad S Deshpande

Reputation: 1412

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"
        }
    }
]

Upvotes: 0

Barbaros Özhan
Barbaros Özhan

Reputation: 65105

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"
    }
  }
]

Upvotes: 1

Related Questions