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.
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 []