Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE deserializing collection with @JsonCreator and ACCEPT_CASE_INSENSITIVE_PROPERTIES when JSON and Java property names match #1854

Closed
rue-jw opened this issue Dec 7, 2017 · 5 comments
Milestone

Comments

@rue-jw
Copy link

rue-jw commented Dec 7, 2017

Attempting to deserialize JSON fails when the following conditions are met:

  • Jackson version >2.8.7 (introduced in 2.8.8)
  • ObjectMapper has MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES enabled.
  • Deserializing to @JsonCreator on constructor or factory method
  • The @JsonProperty name is identical to the Java POJO property name
  • The property is a collection

Stack trace:

feign.FeignException: (was java.lang.NullPointerException) (through reference chain: com.test.jackson.deserialize.Obj["Items"]) reading GET /somepath
	at feign.FeignException.errorReading(FeignException.java:49)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:144)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
	at com.sun.proxy.$Proxy6.fetchOrder(Unknown Source)
	at com.test.jackson.deserialize.ApiClientTest.fetchOrders_deserializeOrders_success(ApiClientTest.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.test.jackson.deserialize.Obj["Items"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1689)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:529)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:416)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1265)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:325)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3051)
	at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:65)
	at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:165)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:133)
	... 28 more
Caused by: java.lang.NullPointerException
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:271)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:519)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:527)
	... 37 more

Sample maven project attached. Runs unit test against a Feign client with JacksonDecoder.
Vary the Jackson version to 2.8.7 or below and it passes.
Disable ACCEPT_CASE_INSENSITIVE_PROPERTIES and it passes.
Use getters instead of @JsonCreator and it passes.

jackson-test.zip

@cowtowncoder
Copy link
Member

cowtowncoder commented Dec 16, 2017

Ok at this point I will need a simplified version to remove all unrelated aspects (client, server framework).
See if I can make something that can be run without additional deps.
Test itself does fail as explained.

Interestingly enough, 3.0.0-SNAPSHOT does not fail, so something in handling has been improved.

cowtowncoder added a commit that referenced this issue Dec 17, 2017
@cowtowncoder
Copy link
Member

Added simplified stand-alone test which reproduces the problem.

@cowtowncoder
Copy link
Member

Quick note on work-around: I haven't quite figured out why assignment of value deserializer fails, at low level, but it is due to mismatch of property names (before being unified).
So the work-around, until fix, is to remove discrepancy wrt declaration

private final List<ChildObj> items;

by either adding name match (@JsonProperty("Items")) OR by ignoring field explicitly (@JsonIgnore). Either works around specific problem.

@cowtowncoder cowtowncoder changed the title NPE deserializing collection with @JsonCreator and ACCEPT_CASE_INSENSITIVE_PROPERTIES when JSON and Java property names match NPE deserializing collection with @JsonCreator and ACCEPT_CASE_INSENSITIVE_PROPERTIES when JSON and Java property names match Dec 18, 2017
@cowtowncoder cowtowncoder added this to the 2.9.4 milestone Dec 18, 2017
@cowtowncoder
Copy link
Member

Looks like there was a conflict in BeanPropertyMap, resulting from separate accessor methods for names that map to same case-insensitive input (Items vs items specifically). Fix is to add second argument to a call.

Unfortunately at this point I think I will only backport the fix to 2.9 branch (in addition to master being updated, although it did not exhibit the bug). I am bit hesitant to try to fix 2.8 since it is nearing end of its maintenance cycle, and since this is not a trivial fix (that is, seems that there is non-zero chance for regressions although all tests obviously pass).
So if at all possible, upgrade to 2.9 would be recommended as soon as possible; and in the meantime use of work-around mentioned above (which will resolve naming problem that triggers the bug).

@rue-jw
Copy link
Author

rue-jw commented Dec 18, 2017

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants