From 9c2dc36166c41bdcdd3bb143bf4cad80376bc06e Mon Sep 17 00:00:00 2001 From: Cowtowncoder Date: Mon, 15 Sep 2014 15:52:31 -0700 Subject: [PATCH] Backport #543 workaround in 2.4 --- release-notes/VERSION | 1 + .../jackson/databind/type/TypeBindings.java | 2 +- .../databind/jsontype/TestWithGenerics.java | 34 +++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/release-notes/VERSION b/release-notes/VERSION index 9d845d6f18..1104fff995 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -5,6 +5,7 @@ Version: 2.4.3 (xx-xxx-2014) (reported by Ian B, tea-dragon@github) #524: @JsonIdentityReference(alwaysAsId = true) Custom resolver is reset to SimpleObjectIdResolver (reported by pkokorev@github) +#543: Problem resolving self-referential generic types - Fixed a problem with `acceptJsonFormatVisitor` with Collection/array types that are marked with `@JsonValue`; could cause NPE in JSON Schema generator module. diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java index 9a92af2f6c..6ebb48926a 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java @@ -299,7 +299,7 @@ protected void _resolveBindings(Type t) } _addPlaceholder(name); // to prevent infinite loops - if (typeParams != null) { + if (typeParams != null && typeParams.length > i) { _bindings.put(name, typeParams[i]); } else { _bindings.put(name, _typeFactory._constructType(varType, this)); diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java index 08214a0c94..4d828107ae 100644 --- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java @@ -11,7 +11,6 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.ser.BeanSerializerFactory; import com.fasterxml.jackson.databind.ser.ResolvableSerializer; -import com.fasterxml.jackson.databind.type.TypeFactory; public class TestWithGenerics extends BaseMapTest { @@ -45,7 +44,11 @@ static class ContainerWithField { public ContainerWithField(T a) { animal = a; } } - // Beans for [JACKSON-387], [JACKSON-430] + static class WrappedContainerWithField { + public ContainerWithField animalContainer; + } + + // Beans for [JACKSON-387], [JACKSON-430] @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@classAttr1") static class MyClass { @@ -114,6 +117,15 @@ protected JsonSerializer constructBeanSerializer(SerializerProvider prov } } + // [Issue#543] + static class ContainerWithTwoAnimals extends ContainerWithField { + public V otherAnimal; + + public ContainerWithTwoAnimals(U a1, V a2) { + super(a1); + otherAnimal = a2; + } + } /* /********************************************************** @@ -121,10 +133,12 @@ protected JsonSerializer constructBeanSerializer(SerializerProvider prov /********************************************************** */ + private final ObjectMapper MAPPER = objectMapper(); + public void testWrapperWithGetter() throws Exception { Dog dog = new Dog("Fluffy", 3); - String json = new ObjectMapper().writeValueAsString(new ContainerWithGetter(dog)); + String json = MAPPER.writeValueAsString(new ContainerWithGetter(dog)); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } @@ -133,7 +147,7 @@ public void testWrapperWithGetter() throws Exception public void testWrapperWithField() throws Exception { Dog dog = new Dog("Fluffy", 3); - String json = new ObjectMapper().writeValueAsString(new ContainerWithField(dog)); + String json = MAPPER.writeValueAsString(new ContainerWithField(dog)); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } @@ -143,8 +157,7 @@ public void testWrapperWithExplicitType() throws Exception { Dog dog = new Dog("Fluffy", 3); ContainerWithGetter c2 = new ContainerWithGetter(dog); - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writerWithType(TypeFactory.defaultInstance().constructParametricType(ContainerWithGetter.class, Animal.class)).writeValueAsString(c2); + String json = MAPPER.writerWithType(MAPPER.getTypeFactory().constructParametricType(ContainerWithGetter.class, Animal.class)).writeValueAsString(c2); if (json.indexOf("\"object-type\":\"doggy\"") < 0) { fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); } @@ -201,4 +214,13 @@ public void testJackson430() throws Exception assertNotNull(mc2.params); assertEquals(1, mc2.params.size()); } + + // [Issue#543] + public void testValueWithMoreGenericParameters() throws Exception + { + WrappedContainerWithField wrappedContainerWithField = new WrappedContainerWithField(); + wrappedContainerWithField.animalContainer = new ContainerWithTwoAnimals(new Dog("d1",1), new Dog("d2",2)); + String json = MAPPER.writeValueAsString(wrappedContainerWithField); + assertNotNull(json); + } }