Skip to content
Advertisement

Deserialize json string with nested array of objects with dynamic key

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 (From comment)

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

Advertisement

Answer

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}}
2 People found this is helpful
Advertisement