Reputation: 3
I am using jackson-core, databind, annotations 2.3.3 jars. I have the following simple class
public class ClassA {
private int value;
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
}
And here is the code to try to deserialize a JSON string to the object:
import com.fasterxml.jackson.databind.ObjectMapper;
...
final ObjectMapper objectMapper = new ObjectMapper();
ClassA request = objectMapper.readValue("{\"Value\": 1}", ClassA.class);
But I am getting the following error: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Value" (class ClassA), not marked as ignorable (one known property: "value"]) at [Source: java.io.StringReader@3bff5976; line: 1, column: 12] (through reference chain: ClassA["Value"])
If I changed the JSON string to lower case then it worked. I thought Jackson would be able to map the value to the setter by following the setter convention. I understand i could add JsonProperty annotation to ClassA to make it work but I cannot modify ClassA in my situation.
I also tried explicitly enabling the following mapping features before calling readValue, but it still got the same error:
import com.fasterxml.jackson.databind.MapperFeature;
...
objectMapper.enable(MapperFeature.AUTO_DETECT_GETTERS);
objectMapper.enable(MapperFeature.AUTO_DETECT_SETTERS);
How can I have Jackson bind to standard getters/setters (getXxx and setXxx) without specify annotation to the class being bound?
Thanks!
Upvotes: 0
Views: 3808
Reputation: 47269
It looks like this is happening because of the default PropertyNamingStrategy
provided by Jackson. From the documentation:
In absence of a registered custom strategy, default Java property naming strategy is used, which leaves field names as is, and removes set/get/is prefix from methods (as well as lower-cases initial sequence of capitalized characters).
The mapper default uses the Java default property naming strategy. If your JSON properties are Pascal Case (not sure because you only provided 1 property) then you can give the mapper the PascalCaseStrategy
.
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy());
ClassA request = objectMapper.readValue("{\"Value\": 1}", ClassA.class);
Upvotes: 1
Reputation: 279990
Jackson follows bean naming conventions.
I understand i could add
JsonProperty
annotation toClassA
to make it work but I cannot modifyClassA
in my situation.
That's where mixins come in handy. Create an abstract
class that has the same method declarations (same getters for example) as ClassA
and annotate them with the appropriate @JsonProperty
annotation. You then register the mixin with the ObjectMapper
and voila! The ObjectMapper
will now use the mixin class as a template for serializing and deserializing ClassA
.
Upvotes: 0