Background:
I am getting mismatchedInputException, when parsing json.
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type java.util.ArrayList<Data>
from Object value (token JsonToken.START_OBJECT
)
Problem:
nodes is a json-array which contains data, which can be either json-object or json-array .
I need to represent this correctly in POJO.
Things Tried: Map<String, Object>, List, ,@JsonDeserialize(using = NodeDeserializer.class)
Below is my nested json document for ref.
{ "parent": { "nodes": [ { "data": { "desc": "a1", "url": "http://a1.a11" } }, { "data": [ { "desc": "b1", "url": "http://b1.b11" }, { "desc": "b2", "url": "http://b2.b21" } ] } ] } }
Below is Pojo Java classes and Runner class, I am using for SER/DE for above Json
Data.java
import lombok.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString @JsonInclude(JsonInclude.Include.NON_NULL) class Data { @JsonProperty("desc") private String desc; @JsonProperty("url") private String url; }
Node.java
import lombok.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString @JsonInclude(JsonInclude.Include.NON_NULL) class Node { @JsonProperty("data") //Map<String, Object> data = new LinkedHashMap<>(); //private List<Object> data; private List<Data> data; }
Parent.java
import lombok.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString @JsonInclude(JsonInclude.Include.NON_NULL) class Parent { @JsonProperty("nodes") private List<Node> nodes; }
Test.java
import lombok.*; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString @JsonInclude(JsonInclude.Include.NON_NULL) public class Test { @JsonProperty("parent") private Parent parent; }
Runner Class
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; public class TestJsonParse { public static void main(String[] args) throws JsonProcessingException { String jsonString = "{n" + " "parent": {n" + " "nodes": [n" + " {n" + " "data": {n" + " "desc": "a1",n" + " "url": "http://a1.a11"n" + " }n" + " },n" + " {n" + " "data": [n" + " {n" + " "desc": "b1",n" + " "url": "http://b1.b11"n" + " },n" + " {n" + " "desc": "b2",n" + " "url": "http://b2.b21"n" + " }n" + " ]n" + " }n" + " ]n" + " }n" + "}"; // print pojo ObjectMapper objectMapper = new ObjectMapper(); Test test = objectMapper.readValue(jsonString, Test.class); System.out.println(test); } }
Advertisement
Answer
How to write common pojo deserializer for json attribute which can be an object and an array both?
It is possible if you use the JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY
deserialization feature consisting of an override for the DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
feature which allows deserialization of JSON non-array values into single-element Java arrays and Collections. So you can annotate the data
field of your Node
class to obtain the expected behaviour:
class Node { @JsonProperty("data") @JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) private List<Data> data; }