Home > other >  Deserialize json string with nested array of objects with dynamic key
Deserialize json string with nested array of objects with dynamic key

Time:07-31

Given the JSON string I need to convert it to my POJO named TransactionInfo

JSON String

{
  "transactionId": "EFODKKXHE003",
  "isSettled": false,
  "transactionProperties": [
    {
      "key1": "Value1"
    },
    {
      "key2": "Value2"
    },
    {
      "key3": "Value3"
    }
  ]
}

POJO

class TransactionInfo {
   String transactionId;
   Boolean isSettled;
   Map<String,String> transactionProperties;
}

Additional Note

After the deserialization, I want to access different keys in the transactionProperties map. If it's converted into a List<Map<String,String>> then it becomes complex. FYI, the keys are guaranteed to be unique so in the end, I want one single flat map. Another point, I don't need to serialize TransactionInfo back to JSON.

What I tried

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.readValue(jsonString, TransactionInfo.class);

But I am getting an exception like below:


Cannot deserialize value of type java.util.LinkedHashMap<java.lang.String,java.lang.Object> from Array value (token JsonToken.START_ARRAY)

Can anyone guide me on how to do that properly? Any help is much appreciated.


Edit

I have already gone through the following post(s) but none of them seems to match my use case

CodePudding user response:

the keys are guaranteed to be unique so in the end, I want one single flat map. Another point, I don't need to serialize TransactionInfo back to JSON.

Since all keys are unique, and you don't care about serialization of this POJO back into JSON, you can transform the list of maps into a map inside a constructor.

public class TransactionInfo {
    String transactionId;
    Boolean isSettled;
    Map<String, String> transactionProperties;

    public TransactionInfo(String transactionId, Boolean isSettled, Map<String, String> transactionProperties) {
        this.transactionId = transactionId;
        this.isSettled = isSettled;
        this.transactionProperties = transactionProperties;
    }

    public TransactionInfo(
        @JsonProperty("transactionId") String transactionId,
        @JsonProperty("isSettled") Boolean isSettled,
        @JsonProperty("transactionProperties") List<Map<String, String>> transactionPropertiesList) {
        
        this.transactionId = transactionId;
        this.isSettled = isSettled;
        this.transactionProperties = transactionPropertiesList.stream()
            .flatMap(map -> map.entrySet().stream())
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue
            ));
    }
}

Code-snippet from the main():

String json = """
            {
               "transactionId": "EFODKKXHE003",
               "isSettled": false,
               "transactionProperties": [
                 {
                   "key1": "Value1"
                 },
                 {
                   "key2": "Value2"
                 },
                 {
                   "key3": "Value3"
                 }
               ]
             }""";

ObjectMapper mapper = new ObjectMapper();
TransactionInfo transactionInfo = mapper.readValue(json, TransactionInfo.class);
System.out.println(transactionInfo);

Output:

TransactionInfo{transactionId='EFODKKXHE003', isSettled=false, transactionProperties={key1=Value1, key2=Value2, key3=Value3}}

CodePudding user response:

One option is to change the type of the transactionProperties field to List<ObjectNode> then iterate over the list and for each element use it's fields() method to retrieve its members

  • Related