Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistent Jackson "Unrecognized field" due to capitalization

Tags:

java

jackson

Jackson seems to have a problem when the second letter of a field name is capitalized.

Take a map of values:

aaBoolean, true   // works
aBoolean, false   // fails
anInt, 0          // works
aString, "a"      // fails

I used Jackson's ObjectMapper.convertValue(map) to create a Java object. Here's a snippet of Java code:

private boolean aaBoolean;  // GOOD
public boolean getAaBoolean() { return aaBoolean; }
public void setAaBoolean(boolean value) { this.aaBoolean=value;}

private boolean aBoolean;  // FAILS!!! Jackson "Unrecognized field"
public boolean getABoolean() { return aBoolean; }
public void setABoolean(boolean value) { this.aBoolean=value;}

I get an error message with all 18 fields. Note the camel case fails when the capital is the second letter:

Unrecognized field "aBoolean" (class Test), not marked as ignorable 
(18 known properties: "anInt", "anullableBoolean", "aboolean", "aaBoolean", 
"lastModifiedDate", "adate", "anullableDate", "astring", "anullableString", 
"createdDate", "anullableFloat", "id", "along", "anullableLong", "createdBy", 
"anullableInt", "lastModifiedBy", "afloat"])

If I change aBoolean to aaBoolean, that passes and Jackson fails on aString.

Per other Stack Overflow posts, I've verified that the field name and getter/setter match (aBoolean is getABoolean() and aaBoolean is getAaBoolean()).

If it matters, here's how the ObjectMapper was created:

ObjectMapper mapper = new ObjectMapper();
mapper.setTimeZone(TimeZone.getTimeZone("CST"));

I can post the full code but I think the above is enough.

I can modify my variable names to get around this, but now I'm curious - is this a bug or am I missing something about how Jackson handles name conversion?

like image 886
baylor Avatar asked Sep 11 '25 14:09

baylor


1 Answers

It looks like the default Jackson behavior through v2.9 is to lowercase any leading upper case getter/setter methods. So "getURLtoServer" becomes "urltoServer".

Jackson source code executing this here: https://github.com/FasterXML/jackson-databind/blob/2.9/src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java#L246

However, the JavaBean spec says to not change any casing if the first two characters are uppercase. So the JavaBean of "getURLtoServer" would be "URLtoServer".

Jackson introduced MapperFeature.USE_STD_BEAN_NAMING as an option to enforce this part of the JavaBean spec. However, it looks like that's being removed in v3.x when it becomes the default behavior: https://github.com/FasterXML/jackson-databind/issues/1772

So for your case, it looks like you can either have the JSON string "aboolean" without using USE_STD_BEAN_NAMING, or else you can have the JSON string "ABoolean" with using USE_STD_BEAN_NAMING.

The other option is to manually specify what you want:

@JsonProperty("aBoolean")
public boolean getABoolean() { return aBoolean; }
like image 53
Dane White Avatar answered Sep 13 '25 04:09

Dane White