I am trying to parse some JSON (full example of the JSON can be seen in this Gist). I show the general structure of the JSON below:
[
{
"title": "Principles of Compiler Design",
"authors": [
"Aho",
"Ullman"
],
"publisher": "Addison Wesley",
"year": 1977
},
{
"title": "Compilers: Principles Techniques and Tools",
"authors": [
"Aho",
"Sethi",
"Ullman"
],
"publisher": "Addison Wesley",
"year": 1985
}
]
I am trying to parse the JSON with Jackson libraries, but I get the following error while testing:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
at [Source: library.json; line: 2, column: 49] (through reference chain: com.acme.datatypes.User["authors"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:163)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:588)
at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StringDeserializer.deserialize(JdkDeserializers.java:90)
at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StringDeserializer.deserialize(JdkDeserializers.java:59)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:336)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:89)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:290)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2563)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1759)
at com.acme.datatypes.UserTest.main(UserTest.java:20)
Here is my code:
User Test class:
public class UserTest {
public static void main(String[] args) throws JsonParseException,
JsonMappingException, IOException {
File jsonFile = new File("library.json");
User user = null;
ObjectMapper mapper = new ObjectMapper();
user = mapper.readValue(jsonFile, User.class);
System.out.println(user.getTitle());
user = mapper.readValue(jsonFile, User.class);
System.out.println(user.getAuthors());
user = mapper.readValue(jsonFile, User.class);
System.out.println(user.getPublisher());
user = mapper.readValue(jsonFile, User.class);
System.out.println(user.getYear());
}
}
User class:
public class User {
private String authors;
private String publisher;
private String title;
private Number year;
public String getAuthors() {
return this.authors;
}
public void setAuthors(String authors) {
this.authors = authors;
}
public String getPublisher() {
return this.publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Number getYear() {
return this.year;
}
public void setYear(Number year) {
this.year = year;
}
}
Does anyone know what the problem might be? Thanks.
Alternatively, you can also use @JsonIgnoreProperties annotation to ignore undeclared properties. The @JsonIgnoreProperties is a class-level annotation in Jackson and it will ignore every property you haven't defined in your POJO.
The Jackson ObjectMapper can parse JSON from a string, stream or file, and create a Java object or object graph representing the parsed JSON. Parsing JSON into Java objects is also referred to as to deserialize Java objects from JSON. The Jackson ObjectMapper can also create JSON from Java objects.
Class JsonProcessingExceptionIntermediate base class for all problems encountered when processing (parsing, generating) JSON content that are not pure I/O problems. Regular IOException s will be passed through as is. Sub-class of IOException for convenience.
public class JsonMappingException extends JsonProcessingException. Checked exception used to signal fatal problems with mapping of content, distinct from low-level I/O problems (signaled using simple IOException s) or data encoding/decoding problems (signaled with JsonParseException , JsonGenerationException ).
Two quick things:
Your User class is defining the authors
property as a String. But in JSON its an array, so you need to use a collections or array type in your Java object. Something like:
private List<String> authors
You repeatedly parse the JSON file in your test class. You only need to parse it once, and you need to use a supertype token, since there is a list of items in the JSON (not just one). You are also using the wrong type to deserialize (User.class). Instead of all these lines:
user = mapper.readValue(jsonFile, User.class);
System.out.println(user.getTitle());
user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing
System.out.println(user.getAuthors());
user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing
System.out.println(user.getPublisher());
user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing
System.out.println(user.getYear());
Just use:
List<User> userList =
mapper.readValue(jsonFile, new TypeReference<List<User>>() {});
Once you get a list of users in your test class you can iterate them using an enhanced for loop.
for(User user : userList) {
System.out.println(user.getTitle());
}
Since you are working with an array, you need to convert it into an array or a list
As Array
MyClass[] myObjects = mapper.readValue(json, MyClass[].class);
As List
List<MyClass> myObjects = mapper.readValue(jsonInput, new TypeReference<List<MyClass>>(){});
User
public class User {
private List<String> authors;
private String publisher;
private String title;
private Number year;
public List<String> getAuthors() {
return this.authors;
}
public void setAuthors(List<String> authors) {
this.authors = authors;
}
public String getPublisher() {
return this.publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Number getYear() {
return this.year;
}
public void setYear(Number year) {
this.year = year;
}
}
Usage:
List<User> l = mapper.readValue(new File(""),new TypeReference<List<User>>() {});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With