Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedded list of Data Object in Jackson

Tags:

I have a JSON structure that looks like this:

{"data": [{"mykey": "someval"}, {"mykey": "someotherval"}], "foo": "bar"}

I also have

public MyClass {
    public String mykey;
}

Now I would like to deserialize the content of "data" of my JSON into a List<MyClass> using Jackson, so I have this code:

ObjectMapper mapper = new ObjectMapper();
List<MyClass> l = (List<MyClass>) mapper.readerFor(new TypeReference<List<MyClass>>(){}).
    withRootName("data").readValue(myJSONString);

However this gives me an exception:

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (FIELD_NAME), 
expected END_OBJECT: Current token not END_OBJECT (to match wrapper object with root name 
'data'), but FIELD_NAME

Anyone know what I need to do to get this parsed?

like image 456
David Bosschaert Avatar asked Mar 06 '17 15:03

David Bosschaert


People also ask

How do I map nested values with Jackson?

Mapping With Annotations To map the nested brandName property, we first need to unpack the nested brand object to a Map and extract the name property. To map ownerName, we unpack the nested owner object to a Map and extract its name property.

What is the use of @JsonRootName?

@JsonRootName allows to have a root node specified over the JSON. We need to enable wrap root value as well.

How does Jackson read nested JSON?

A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.

What is JsonProperty annotation Java?

The @JsonProperty annotation is used to map property names with JSON keys during serialization and deserialization. By default, if you try to serialize a POJO, the generated JSON will have keys mapped to the fields of the POJO.


1 Answers

Update

List<MyClass> l = (List<MyClass>) mapper.readValue(mapper.readTree(myJSONString).findPath("data").toString(),
                                  new TypeReference<List<MyClass>>(){});

This one line will retrieve the list you are looking for. The problem with what you are trying to do is you are trying to deserialize for the case where the data constitutes the JSON like

{"data":[{"mykey": "someval"}, {"mykey": "someotherval"}]}

But your JSON has additional values which is causing the issue. The above code isolates the data array using the Jackson JSON tree parser and then deserailize it in to the list.

Initial answer

Have a root object so that you can capture the list within that object.

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"data"
})
public class Root {

@JsonProperty("data")
private List<MyClass> data = null;

@JsonProperty("data")
public List<MyClass> getData() {
return data;
}

@JsonProperty("data")
public void setData(List<MyClass> data) {
this.data = data;
}
}

Now use the objectMapper to deserialize to this object.

Root root = mapper.readValue(myJSONString,Root.class);

Let me know how it works out.

like image 137
Coder Avatar answered Sep 23 '22 10:09

Coder