-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Json serialization fails or a specific case that contains generics & static methods with generic parameters #2821
Comments
I just hit the same error. My simple test case @JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
data class GenericResponse<T>(
val data: T? = null,
val extensions: Map<Any, Any>? = null
)
data class MyData(val foo: Int)
fun main() {
val mapper = jacksonObjectMapper()
val input =
"""{"data":{"foo":1}, "extensions":{"bar":2}}"""
val response: GenericResponse<MyData> = mapper.readValue(input)
println(response)
} Above works fine in with Jackson
|
Having similar issues. When I change @dariuszkuc 's example this way, it works: data class GenericResponse<T>(
val data: T? = null,
val extensions: Map<Any, Any>? = null
)
data class MyData(val foo: Int)
fun main() {
val typeRef = GenericResponse(MyData(1), emptyMap())::class.java
val mapper = jacksonObjectMapper()
val input =
"""{"data":{"foo":1}, "extensions":{"bar":2}}"""
val response: GenericResponse<MyData> = mapper.readValue(input, typeRef)
println(response)
} I believe the problem might be somewhere in the |
Quick note: unfortunately Kotlin-based examples won't help a lot when working on databind (although they are obviously fine for Kotlin module), as I can not use them for unit tests. But maybe I can simplify the original test which is Java only I think. |
I hope to look into this soon -- I suspect that @lhotari is correct about issue related to (that is, fix that may have caused regression). I am guessing that things might have worked as a side-effect. Was able to test against 2.12.0-SNAPSHOT with following def in
and looks like the problem still persists (which is not entirely unexpected). What I need is then just self-contained version to add as unit test; however, should also be able to import existing project into IDE for some investigation once I have time. |
Breaking Java code similar to the above Kotlin example would be: public class ObjectMapperGenericClassTest extends BaseTest {
static final String JSON = "{ \"field\": { \"number\": 1 }, \"map\": { \"key\": \"value\" } }";
static class GenericEntity<T> {
T field;
Map map;
public void setField(T field) {
this.field = field;
}
public T getField() {
return field;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
static class SimpleEntity {
Integer number;
public void setNumber(Integer number) {
this.number = number;
}
public Integer getNumber() {
return number;
}
}
public void test() throws Exception {
ObjectMapper m = new ObjectMapper();
GenericEntity<SimpleEntity> genericEntity = m.readValue(JSON, new TypeReference<GenericEntity<SimpleEntity>>() {});
}
} It works in 2.11.2 if I add any type parameter to the static final String JSON = "{ \"map\": { \"key\": \"value\" } }";
static class GenericEntity {
Map map;
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
public void test throws Exception {
ObjectMapper m = new ObjectMapper();
GenericEntity genericEntity = m.readValue(JSON, new TypeReference<GenericEntity>() {});
} |
In my real case I am actually seeing:
I am still working on a minimal example for that. |
Thanks for the repros @dariuszkuc and @MartinTeeVarga . It seems that the issue with Kotlin and the example that @MartinTeeVarga provided are somewhat different than what I have. In my case, the issue is in serialization. I assume that the problems are related. public class JacksonBugIsolatedTest {
static final class Wrapper {
// if Entity<?> -> Entity , the test passes
private final List<Entity<?>> entities;
@JsonCreator
public Wrapper(List<Entity<?>> entities) {
this.entities = entities;
}
public List<Entity<?>> getEntities() {
return this.entities;
}
}
public static class Entity<T> {
@JsonIgnore
private final Attributes attributes;
private final T data;
public Entity(Attributes attributes, T data) {
this.attributes = attributes;
this.data = data;
}
// if @JsonUnwrapped is removed, the test passes
@JsonUnwrapped
public Attributes getAttributes() {
return attributes;
}
public T getData() {
return data;
}
@JsonCreator
public static <T> Entity<T> create(Attributes attributes, T data) {
return new Entity<>(attributes, data);
}
}
public static class Attributes {
private final String id;
public Attributes(String id) {
this.id = id;
}
public String getId() {
return id;
}
@JsonCreator
public static Attributes create(String id) {
return new Attributes(id);
}
// if this method is removed, the test passes
public static Attributes dummyMethod(Map attributes) {
return null;
}
}
// this test passes with Jackson 2.11.1, but fails with Jackson 2.11.2
@Test
public void reproduceSerializerBug() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
Entity<String> entity = new Entity<>(new Attributes("id"), "hello");
Wrapper val = new Wrapper(Collections.singletonList(entity));
// fails with com.fasterxml.jackson.databind.JsonMappingException: Strange Map type java.util.Map: cannot determine type parameters (through reference chain: com.github.lhotari.jacksonbug.JacksonBugIsolatedTest$Wrapper["entities"]->java.util.Collections$SingletonList[0]->com.github.lhotari.jacksonbug.JacksonBugIsolatedTest$Entity["attributes"])
System.out.println(objectMapper.writeValueAsString(val));
}
} This test class is also available in the repro repo: https://github.com/lhotari/jackson-bug-2020-08-18/blob/master/src/test/java/com/github/lhotari/jacksonbug/JacksonBugIsolatedTest.java Also tried to add the test to jackson-databind: lhotari@ecdfd6c |
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. |
Hmmh. |
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). |
Ok, had to make a bit more fundamental change than what I was hoping for: basically clear out Looking forward to other test failures, if @MartinTeeVarga or @dariuszkuc can provide one. |
Will file a separate issue for @MartinTeeVarga 's issue: that is similar, but does not require static method to trigger. |
Follow-up issue: #2846. |
@cowtowncoder any eta on the 2.11.3 release? I would like to test it out but would rather use released version |
@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. With all that, hopefully by end of September or first week of October. |
just to close up the loop -> |
@dariuszkuc thank you for confirming this. |
spring-boot-dependencies setter jackson til 2.11.2 som inneholder en liten bugg. buggen gjør at deserialisering av graphqlResponses ikke fungerer som forventet. Les mer; ExpediaGroup/graphql-kotlin#850 FasterXML/jackson-databind#2821
Hi @cowtowncoder , class CloudEventSerializer : Serializer<CloudEventImpl<Foo>> {
override fun serialize(topic: String?, data: CloudEventImpl<Foo>?): ByteArray = ObjectMapper()
.writerFor(object : TypeReference<CloudEventImpl<Foo>>() {})
.writeValueAsBytes(data)
} The problem persists for following versions:
Interestingly, when one skips |
@superdurszlak I would need a full, stand-alone reproduction. If that is possible, please file a new issue and I can take a look. The part about |
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:
fails with exception.
Comments
Changes in TypeFactory.constructType in 2.11.2 for #2796 might have caused the change in behavior.
Looks like the problem that 910edfb 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:
https://github.com/cloudevents/sdk-java/blob/361a34cc639ddaa75b2a5080f117fc282be7625b/api/src/main/java/io/cloudevents/v1/AttributesImpl.java#L172-L173
The text was updated successfully, but these errors were encountered: