jackson-databind: Json serialization fails or a specific case that contains generics & static methods with generic parameters
Reproducing the issue
I wasn’t able to analyze the exact reason, however I have created a repository that reproduces the issue. The problem seem to occur only with a certain structure and I wasn’t yet able to isolate it further.
The test case that reproduces the issue References CloudEvent, CloudEventImpl and AttributesImpl classes from CloudEvents Java SDK 1.3.0 .
to reproduce:
git clone https://github.com/lhotari/jackson-bug-2020-08-18
cd jackson-bug-2020-08-18
./gradlew test
fails with exception.
com.github.lhotari.jacksonbug.JacksonBugTest > reproduceSerializerBug() FAILED
com.fasterxml.jackson.databind.JsonMappingException: Strange Map type java.util.Map: cannot determine type parameters (through reference chain: com.github.lhotari.jacksonbug.JacksonBugTest$MyValue["events"]->java.util.Collections$SingletonList[0]->io.cloudevents.v1.CloudEventImpl["attributes"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:295)
at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1309)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1447)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:562)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter._findAndAddDynamic(UnwrappingBeanPropertyWriter.java:211)
at com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter.serializeAsField(UnwrappingBeanPropertyWriter.java:102)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4407)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3661)
at com.github.lhotari.jacksonbug.JacksonBugTest.reproduceSerializerBug(JacksonBugTest.java:39)
Caused by:
java.lang.IllegalArgumentException: Strange Map type java.util.Map: cannot determine type parameters
at com.fasterxml.jackson.databind.type.TypeFactory._mapType(TypeFactory.java:1178)
at com.fasterxml.jackson.databind.type.TypeFactory._fromWellKnownClass(TypeFactory.java:1471)
at com.fasterxml.jackson.databind.type.TypeFactory._fromClass(TypeFactory.java:1414)
at com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeFactory.java:705)
at com.fasterxml.jackson.databind.introspect.AnnotatedClass.resolveType(AnnotatedClass.java:229)
at com.fasterxml.jackson.databind.introspect.AnnotatedMethod.getParameterType(AnnotatedMethod.java:143)
at com.fasterxml.jackson.databind.introspect.AnnotatedWithParams.getParameter(AnnotatedWithParams.java:86)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addCreators(POJOPropertiesCollector.java:500)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll(POJOPropertiesCollector.java:327)
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getJsonValueAccessor(POJOPropertiesCollector.java:203)
at com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findJsonValueAccessor(BasicBeanDescription.java:252)
at com.fasterxml.jackson.databind.ser.BasicSerializerFactory.findSerializerByAnnotations(BasicSerializerFactory.java:396)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:216)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:165)
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1474)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1442)
... 16 more
Comments
- Test passes with Jackson 2.11.1 version, but fails with 2.11.2 .
- Diff between Jackson 2.11.2 and 2.11.1
Changes in TypeFactory.constructType in 2.11.2 for https://github.com/FasterXML/jackson-databind/issues/2796 might have caused the change in behavior. Looks like the problem that https://github.com/FasterXML/jackson-databind/commit/910edfb634f55cdb8d78ac7d9caf00d8133a11e6 fixes could have been similar.
By debugging it can be seen that resolving parameter types with the bindings in AnnotedClass doesn’t produce the correct result.
Another observation here is that the method that is been processed by Jackson is produced by a lambda. The method name in the repro case is private static void io.cloudevents.v1.AttributesImpl.lambda$marshal$3(java.util.Map,java.time.ZonedDateTime)
The failure seems to happen when Jackson tries to resolve the parameters for this method generated by the lambda defined at this location:
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 19 (11 by maintainers)
Commits related to this issue
- Add test for #2821 — committed to lhotari/jackson-databind by lhotari 4 years ago
- Minor error message improvement wrt #2821 — committed to FasterXML/jackson-databind by cowtowncoder 4 years ago
- Fix #2821 — committed to FasterXML/jackson-databind by cowtowncoder 4 years ago
- [KAIZEN-0] sette jackson-versioner eksplisitt til ny versjon spring-boot-dependencies setter jackson til 2.11.2 som inneholder en liten bugg. buggen gjør at deserialisering av graphqlResponses ikke f... — committed to navikt/modiapersonoversikt-api by nutgaard 4 years ago
@dariuszkuc I need to balance a few things so no firm answer: hoping to get 2.12.0-rc1 out first, followed by 2.11.3. Release takes a while (couple of hours) and it has only been bit over month since 2.11.2. At the same time I do realize that this is actually a significant issue for many users so it is high priority.
With all that, hopefully by end of September or first week of October.
I just hit the same error. My simple test case
Above works fine in with Jackson
2.11.1
but fails in2.11.2
with following exceptionjust to close up the loop ->
2.11.3
does solve my issue and seems to be working fine.Ok, had to make a bit more fundamental change than what I was hoping for: basically clear out
TypeBindings
passed for static factory methods. This seems correct to me, although I am not quite sure why failure occurred (meaning that I suspect there is some other problem affecting resolution). So I don’t think change is wrong, I just didn’t think it should have affected anything. No new test failures, although would not be surprised if some edge case somewhere might have changed.Looking forward to other test failures, if @MartinTeeVarga or @dariuszkuc can provide one.
Ok, no problem, I can reproduce this. What appears to be the problem is that type bindings passed are for enclosing class, not for type resolved; and number of parameters mismatches (it is all around wrong value but might “work” otherwise since no actual binding information is available just placeholder).
Thank you everyone for help here! Yes, it is possible there are multiple issues and they might need separate fixes (or at least test cases). I’ll first focus on @lhotari 's case.
Breaking Java code similar to the above Kotlin example would be:
It works in 2.11.2 if I add any type parameter to the
Map
and it also works if I remove the type parameter<T>
and the wholeSimpleEntity
and keep theMap
without type parameter: