rbqa
rbqa

Reputation: 43

How to deserialize with jackson objectmapper

I want to convert a json (shown below) into a java object. I have created java classes for the json objects without using any jackson annotations for now.

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestJunkie {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws Exception {
        String json = "{\r\n" + 
                "   \"Info\":{\r\n" + 
                "       \"prop1\": \"value1\",\r\n" + 
                "       \"prop2\": \"value2\",\r\n" + 
                "       \"prop3\": \"value3\"\r\n" + 
                "   },\r\n" + 
                "   \"Data\":{\r\n" + 
                "       \"prop1\": \"value1\",\r\n" + 
                "       \"prop2\": \"value2\"\r\n" + 
                "   }\r\n" + 
                "}";

        Pack pack = objectMapper.readValue(json, Pack.class);
        System.out.println(pack);
    }

}

I converted the above Json object into a Java class called "Pack" below:

import org.apache.commons.lang3.builder.ToStringBuilder;

public class Pack {

    private Info info;
    private Data data;

    public Info getInfo() {
        return info;
    }

    public void setInfo(Info info) {
        this.info = info;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("info", info).append("data", data).toString();
    }

}

I have deliberately omitted the classes for Info and Data. Their variables, getters, setters match the json. I can include them if you want.

I get the following exception. Why does this exception occur & how do I fix it ?

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Info" (class com.tester.Jacksons.Pack), not marked as ignorable (2 known properties: "data", "info"])
 at [Source: (String)"{
    "Info":{
        "prop1": "value1",
        "prop2": "value2",
        "prop3": "value3"
    },
    "Data":{
        "prop1": "value1",
        "prop2": "value2"
    }
}"; line: 2, column: 10] (through reference chain: com.tester.Jacksons.Pack["Info"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1582)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1560)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
    at com.tester.Jacksons.TestJunkie.main(TestJunkie.java:22)

Upvotes: 2

Views: 4248

Answers (2)

Vinay Prajapati
Vinay Prajapati

Reputation: 7546

Your properties inside Pack are not matching the names because in json it's starting with capital case letter. Hence, update Pack as follows:

import org.apache.commons.lang3.builder.ToStringBuilder;

public class Pack {

    @JsonProperty("Info")
    private Info info;
    @JsonProperty("Data")
    private Data data;

    public Info getInfo() {
        return info;
    }

    public void setInfo(Info info) {
        this.info = info;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("info", info).append("data", data).toString();
    }

}

Also, in case there are properties which are not specified in Info or Data class. Use @JsonIgnoreProperties(ignoreUnknown = true) annotation on class to Ignore unknown properties.

Updates

Using annotations could not be very handy if you have to use same Classes say as Hibernate Entities or in other places. Hence, My recommendation is that you perform serialization and deserialization using Dtos and then later put values from these Dtos to your other objects wherever you need to. You could use good apis like mapstruct to do such creation of objects.

Upvotes: 0

Magnus
Magnus

Reputation: 8308

Your object's keys are lower case and in the json they are upper-camel-case. If this naming scheme is consistent you can just set the naming stategy on the object mapper.

mapper.setPropertyNamingStrategy(PropertyNamingStrategy.UpperCamelCaseStrategy);

Upvotes: 1

Related Questions