Chris
Chris

Reputation: 1401

Deserialize JSON Object with nested attributes

I am trying to deserialize a json object with the attributes

Where the first key name is unknown, while the inner map always contains two attributes named "key1" and "key2".

{
   "operation_rand":
   {
      "key1": 1005, 
      "key2": 5
   }
}

I have the code :

Operation.java

public class Operation {
    private Map<String, Map<String, Integer>> operationDetails = new HashMap<>();
    
    @JsonAnyGetter
    public Map<String, Map<String, Integer>> getOperation() {
        return operationDetails;
    }
} 

Main

ObjectMapper mapper = new ObjectMapper();
   
Operation op = mapper.readValue(jsonData, Operation.class); 
Map<String, Map<String, Integer>> oDetails = address.getOperation();

However I get the error: Can not deserialize instance of java.lang.String out of START_OBJECT token at line: 1, column: 25, which is where the inner map starts.

Any ideas on how I can map the inner map? I can grab the correct value if the map was only one layer deep.

{
   "operation_rand": 100
}

And adjusting the above maps to just Map<String, Integer>

Upvotes: 0

Views: 332

Answers (3)

JPA
JPA

Reputation: 174

You need an Object Representation for the expected JSON a Gson dependency

Class for the Object


    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.annotation.JsonRootName;

    @JsonRootName("operation_rand")
    public class OperationRand{
    @JsonProperty("key1")
    private int key1;
    @JsonProperty("key2")
    private int key2;

    public int getKey1() {
        return key1;
    }

    public void setKey1(int key1) {
        this.key1 = key1;
    }

    public int getKey2() {
        return key2;
    }

    public void setKey2(int key2) {
        this.key2 = key2;
    }

    public OperationRand(int key1, int key2) {
        this.key1 = key1;
        this.key2 = key2;
    }

    @Override
    public String toString() {
        return "OperationRand{" +
                "key1=" + key1 +
                ", key2=" + key2 +
                '}';
    }
    }

Gson From Google

    <dependency>

        <groupId>com.google.code.gson</groupId>

        <artifactId>gson</artifactId>

    </dependency>

Then,

    String json ="{\n" +
                "   \"operation_rand\":\n" +
                "   {\n" +
                "      \"key1\": 1005, \n" +
                "      \"key2\": 5\n" +
                "   }\n" +
                "}";
    Gson gson = new Gson();
    OperationRand res = gson.fromJson(json, OperationRand.class);

    System.out.println(res);
    

[EDIT]for the Changing operation_rand I would use the object for the nonchanging Fields


    import lombok.*;
    
    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    public class Key {
    int key1;
    int key2;
    }

in the main


    Gson gson = new Gson();
    Map<String,Key> rest = gson.fromJson(json,HashMap.class);
    System.out.println(rest);

Upvotes: 2

You just need to simplify the class like this:

public class Operation {
    @JsonProperty("operation_rand")
    private Map operationDetails;
    
    public Map getOperation() {
        return operationDetails;
    }
} 

Upvotes: 0

melody zhou
melody zhou

Reputation: 148

100 is not Map<String, Integer>.

Maybe use Map<String,Object> instead of Map<String, Map<String, Integer>>.

By instanceof Integerinstanceof Map to determine the type.

Upvotes: 0

Related Questions