Skip to content
Advertisement

Jackson ObjectMapper returns null when Object variable is set to Private

I am given this escaped JSON

"{"UniqueId":[],"CustomerOffers":{},"Success":false,"ErrorMessages":["Test Message"],"ErrorType":"GeneralError"}"

and I need to convert it to Java object using Jackson.

// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'

I created the class:

public class Data {

    private List<UUID> UniqueId;
    private Map<Integer, List<Integer>> CustomerOffers;
    private Boolean Success;
    private List<String> ErrorMessages;
    private String ErrorType;

    // getter, setters
}

Then I created the method to convert it

public class Deserializing {

    public void processing(String input) {

        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);



        String jsonInString = ""{"UniqueId":[],"CustomerOffers":{},"Success":false,"ErrorMessages":["Test Message"],"ErrorType":"GeneralError"}"";
        String newJSON = org.apache.commons.lang3.StringEscapeUtils.unescapeJava(jsonInString);
        newJSON= newJSON.substring(1, jsonInString.length()-1);


            try {
            // JSON string to Java object
            Data data = mapper.readValue(newJSON, Data.class); 
            System.out.println(data);

            System.out.println("Get Success "+ data.getSuccess());  // return "false" if Data object is public ; null if private
            System.out.println("Get UniqueID " + data.getUniqueId()); // return [] if Data object is public ; null if private

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Whichever variables in Data class that are set to public, then I will get the corresponding value when I call getters. Whichever variables in Data class that are set to private, then I will get null when I call getters.

Getters and Setters are always public.

I am wondering, why ObjectMapper can’t map the object if it is set to private? I could set it to public, but that is not best practice.

Advertisement

Answer

The issue is that Jackson will always assume setSuccess() & getSuccess() will be used for a success field, not Success. JSON field names starting with uppercase letters need to be supported by @JsonProperty. Java has a convention where class members always start with lowercase letters, you can realize that by using this annotation.

When you make fields private, you force Jackson to utilize setters, and the above conflict makes it impossible to properly deserialize the Data object.

Solution is to do;

public class Data {

    @JsonProperty("UniqueId")
    private List<UUID> uniqueId;
    @JsonProperty("CustomerOffers")
    private Map<Integer, List<Integer>> customerOffers;
    @JsonProperty("Success")
    private Boolean success;
    @JsonProperty("ErrorMessages")
    private List<String> errorMessages;
    @JsonProperty("ErrorType")
    private String errorType;

    // getter&setters
}

Then you will see the values deserialized properly into a Java object;

Get success false
Get uniqueID []
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement