Incompatible FAIL_ON_MISSING_PRIMITIVE_PROPERTIES and field level @JsonProperty
See original GitHub issueDescribe the bug The FAIL_ON_MISSING_PRIMITIVE_PROPERTIES is not working properly with field level @JsonProperty annotation. The @JsonProperty annotation is simply ignored.
Version information Currently latest 2.12, Java 15.0.1
To Reproduce If you have a way to reproduce this with:
- You can use the JUnit 5 test below to reproduce the issue:
class JsonPropertyAndFailOnNullForPrimitivesTest {
@Test
void test() throws JsonProcessingException {
assertEquals(
JsonMapper.builder()
.addModules(new ParameterNamesModule())
.constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
.enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
.build()
.readValue("{\"aa\": 8}", TestClass.class)
.a,
8);
}
private static class TestClass {
@JsonProperty("aa")
private final int a;
TestClass(int a) {
this.a = a;
}
}
}
- The test fails with the following error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot map `null` into type int (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)
at [Source: (String)"{"aa": 8}"; line: 1, column: 9] (through reference chain: jackson.test.JsonPropertyAndFailOnNullForPrimitivesTest$TestClass["a"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1577)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer.getNullValue(NumberDeserializers.java:175)
at com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer._findMissing(PropertyValueBuffer.java:204)
at com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer.getParameters(PropertyValueBuffer.java:160)
at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:288)
at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:202)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:520)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1390)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:362)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4591)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3546)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3514)
at jackson.test.JsonPropertyAndFailOnNullForPrimitivesTest.test(JsonPropertyAndFailOnNullForPrimitivesTest.java:23)
- Note that other combinations work - not using a primitive type, moving the annotation on the constructor parameter or disabling the FAIL_ON_NULL_FOR_PRIMITIVES feature.
The issue seems to be unrelated to the fact that I use a single argument constructor, I used single property for simlicity in the test. In other words, the new
.constructorDetector(ConstructorDetector.USE_PROPERTIES_BASED)
appears to be irrelevant for this bug.
Expected behavior The FAIL_ON_MISSING_PRIMITIVE_PROPERTIES feature should be aware of property names mapping through @JsonProperty when used on fields.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:9 (6 by maintainers)
Top Results From Across the Web
java - When is the @JsonProperty property used and what is it ...
Here's a good example. I use it to rename the variable because the JSON is coming from a .Net environment where properties start...
Read more >Duplicate properties with upper-case field name and ... - GitHub
Duplicate properties with upper-case field name and JsonProperty annotation ... Not a bug but results from incompatible field/getter/setter naming -- fields ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@cowtowncoder Seems like I’m doing a really great job as a rubber duck 🤞
@GeorgiPetkov No the problem is that:
null
must be passed as placeholder (constructor must get some value for the argumentint
since you haveFAIL_ON_NULL_PRIMITIVES
In addition there is field
a
renamed asaa
into which incoming value is actually mapped (as tofinal
, it’s just a detour for discussion but it is possible to prevent use of final fields as setters). Sonull
comes from absence of value in this case.Now: normally there should be association between field and constructor parameter, as their implicit names match: and after this linkage exist, they are part of a single logical property and that property would get renamed as
aa
. Further, constructor parameter having higher precedence would make it be used and field essentially ignored for deserialization.This linkage, in turn, is missing because fields, methods, and name-annotated constructor parameters are introspected by
POJOPropertiesCollector
(originally all ctor parameters had to be annotated, before Java 5) – but ones which implicit names are only handled at a later point. The end result is that while both accessors are found, annotation “sharing” across accessors does not work – annotation merging occurs inPOJOPropertiesCollector
This does give me an idea, however, regarding possibly (fingers crossed) finding linkage via implicit name, in addition to explicit name (explicit meaning “defined by annotation” and implicit “name derived from field/method name in bytecode”). While it would not enable annotation merging per se, it could cover this case where the only effect of annotation is renaming.