Why is Jackson ignoring the @JsonCreator annotation in my autogenerated POJO Enum?
As usual, there is a very simple solution to my problem:
I have a JSON schema snippet that defines the following enum:
"title" : {
"type": "string",
"enum": ["Mr", "Miss", "Mrs", "Ms"],
"description": "The person title"
}
My company structure uses jsonschema2pojo and maven to create the required POJO ( Title
lives in Clazz
as Title
part Clazz
of the JSON schema - with clazz as the generated name - replace it with employee or customer or whatever you like):
Generated by POJO
@Generated("org.jsonschema2pojo")
public static enum Title {
MR("Mr"),
MISS("Miss"),
MRS("Mrs"),
MS("Ms");
private final String value;
private static Map<String, Clazz.Title> constants = new HashMap<String, Clazz.Title>();
static {
for (Clazz.Title c: values()) {
constants.put(c.value, c);
}
}
private Title(String value) {
this.value = value;
}
@JsonValue
@Override
public String toString() {
return this.value;
}
@JsonCreator
public static Clazz.Title fromValue(String value) {
Clazz.Title constant = constants.get(value);
if (constant == null) {
throw new IllegalArgumentException(value);
} else {
return constant;
}
}
}
When I run a request containing the following against it:
...
"title" : "Mr",
...
I am getting this error thrown at me:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of com.example.foo.representations.jaxb.Clazz$Title from String value 'Mr': value not one of declared Enum instance names: [Mr, Miss, Mrs, Ms] at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination$1@1a372b7; line: 4, column: 3] (through reference chain: com.example.foo.representations.jaxb.MySchema["Clazz"]->com.example.foo.representations.jaxb.Clazz["title"])
Obviously "Mr" is in the Enum.
When debugging, I see it going through the following classes ( stack ):
findEnum():120, EnumResolver (com.fasterxml.jackson.databind.util)
deserialize():79, EnumDeserializer (com.fasterxml.jackson.databind.deser.std)
They seem to be interested in Enum keys (ie constants like " MR
" instead of " MR
"). I'm guessing the annotation @JsonCreator
is being ignored for some reason.
Any idea how I can fix this problem?
Is there a config value that can be set anywhere that can cause this behavior? (I work on large projects, if I know what I need to look for, I can find the code base, maybe another developer "misconfigured" something somewhere ...) Or maybe the problem that Title
lives in Clazz
? Do I need to cast @JsonProperty
for a good grade? (If so, how exactly?)
We are using jackson-core, -nnotes and -databind 2.4.2.
Update . I tried this as a separate project with the following code and it worked flawlessly - which means there must be some setting that does not take the annotation into account ...
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
Clazz value = mapper.readValue(new File("resources/data.json"), Clazz.class);
source to share
So it turned out that the following was done in our Spring configuration:
<bean id="mapper" class="com.example.foo.jaxb.links.JsonMapper" />
<!-- ... -->
<jaxrs:providers>
<bean id="jsonprovider"
class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
<constructor-arg ref="mapper" />
<constructor-arg>
<value></value>
</constructor-arg>
</bean>
</jaxrs:providers>
Jsonmapper extends com.fasterxml.jackson.databind.ObjectMapper
and basically sets Jackson's settings to itself in its constructor. However, one thing that I missed in my despair was a bit of code:
// use JAXB annotations (only)
setAnnotationIntrospector(new JaxbAnnotationIntrospector(
com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance()));
And that pretty much does what he says in tin seems to be: he doesn't let Jackson evaluate annotations @JsonCreator
and @JsonValue
. After the Jackson annotation suppressor disappeared, all is well.
I'd like to understand how this works, so if anyone has helpful links to docs / instructions / guides / books for Spring stuff or annotation suppression it would be greatly appreciated. But in the meantime, this fixes my problem. :)
source to share