Handling json deserialization error

This post explains how to handle errors generated while deserializing the json file.

This can be achieved by implementing an interface “DeserializationProblemHandler” provided by jackson framework as shown below

UnMarshallingErrorHandler


package package1;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;

public class UnMarshallingErrorHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt,
            JsonParser jp, JsonDeserializer deserializer,
            Object beanOrClass, String propertyName) throws IOException,
            JsonProcessingException {
        boolean result = false;
        super.handleUnknownProperty(ctxt, jp, deserializer, beanOrClass,
                propertyName);
        System.out.println("Property with name '" + propertyName + "' doesn't exist in Class of type '" + beanOrClass.getClass().getName() + "'");
        return true;
    }
}

In the above code, we are implementing the interface and add our handling logic in “handleUnknownProperty” method. The Jackson framework passes the information to the interface implementers
1) DeserializationContext ctxt
2) JsonParser jp
3) JsonDeserializer deserializer
4) Object beanOrClass
5) String propertyName

Main information needed for us is “beanOrClass” and “propertyName”

beanOrClass –> will have either the bean instance being serialized or Class object that indicates the type of object being created.

propertyName –> the name of the property for which deserializer didn’t find the appropriate setter method to set in the class.

In the above method we are returning true to inform the deserialization process that we have handled the error and it can continue deserializing.

We have to return false, if we want to stop the deserialization immediately. In this case an exception is thrown or content is skipped based on the configuration.

Below is the main code

Main Class


package package1;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;

public class UnMarshallingDemo2 {
    public static void main(String[] args) throws JsonMappingException, JsonGenerationException, IOException {
        File file = new File("user1.json");
        
        ObjectMapper objectMapper = new ObjectMapper();
        DeserializationProblemHandler deserializationProblemHandler = new UnMarshallingErrorHandler();
        objectMapper.addHandler(deserializationProblemHandler);
        User user = objectMapper.readValue(file, User.class);
        System.out.println(user);
    }
}

Information about the class to be deserialized

User


package package1;

public class User {
    private Name name;
    private String ssn;
    private String sex;
    private int age;
    private PhoneNumber[] phoneNumbers;
    
    public Name getName() {
        return name;
    }
    public void setName(Name name) {
        this.name = name;
    }
    public String getSsn() {
        return ssn;
    }
    public void setSsn(String ssn) {
        this.ssn = ssn;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public PhoneNumber[] getPhoneNumbers() {
        return phoneNumbers;
    }
    public void setPhoneNumbers(PhoneNumber[] phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(name).append(",");
        sb.append(ssn).append(",");
        sb.append(sex).append(",");
        sb.append(age).append(",");
        
        for(PhoneNumber phoneNumber : phoneNumbers) {
            sb.append(phoneNumber).append(",");
        }
        sb.append("}");
        return sb.toString();
    }
}

Name


package package1;

public class Name {
    private String firstName;
    private String lastName;
    
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(firstName).append(",");
        sb.append(lastName);
        sb.append("}");
        
        return sb.toString();
    }
}


package package1;

public class PhoneNumber {
    private String areaCode;
    private String part1;
    private String part2;
    
    public String getAreaCode() {
        return areaCode;
    }
    public void setAreaCode(String areaCode) {
        this.areaCode = areaCode;
    }
    public String getPart1() {
        return part1;
    }
    public void setPart1(String part1) {
        this.part1 = part1;
    }
    public String getPart2() {
        return part2;
    }
    public void setPart2(String part2) {
        this.part2 = part2;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(areaCode).append("-");
        sb.append(part1).append("-");
        sb.append(part2);
        sb.append("}");
        
        return sb.toString();
    }
}

Json data


{
    "name": {
        "firstName":"firstName1",
        "lastName":"lastName1"
        },
    "ssn":"ssn1",
    "sex":"M",
    "age":28,
    "phoneNumbers":[
            {
                "areaCode":"111",
                "part1":"222",
                "part2":"3333"
            },
            {
                "areaCode":"444",
                "part1":"555",
                "part2":"6666"
            }
            ],
    "numbers":[1,2,3,4]
}

In the above json example, “numbers” is a property that doesn’t exist in User class. So when the above code is executed we will get the below error

Output when true is returned

Property with name ‘numbers’ doesn’t exist in Class of type ‘package1.User’
{{firstName1,lastName1},ssn1,M,28,{111-222-3333},{444-555-6666},}

Output when false is returned

Property with name ‘numbers’ doesn’t exist in Class of type ‘package1.User’
Exception in thread “main” com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “numbers” (class package1.User), not marked as ignorable (5 known properties: “name”, “phoneNumbers”, “ssn”, “age”, “sex”])
at [Source: user1.json; line: 21, column: 13] (through reference chain: package1.User[“numbers”])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:851)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1085)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1389)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1367)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:266)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2691)
at package1.UnMarshallingDemo2.main(UnMarshallingDemo2.java:18)

Leave a Reply