diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java index b29f4df1de..103a098566 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java @@ -221,12 +221,6 @@ private List _findPotentialFactories(JavaType type, Class pr if (candidates == null) { return Collections.emptyList(); } - // 05-Sep-2020, tatu: Important fix wrt [databind#2821] -- static methods - // do NOT have type binding context of the surrounding class and although - // passing that should not break things, it appears to... Regardless, - // it should not be needed or useful as those bindings are only available - // to non-static members - TypeResolutionContext typeResCtxt = new TypeResolutionContext.Empty(_typeFactory); int factoryCount = candidates.size(); List result = new ArrayList<>(factoryCount); @@ -250,8 +244,7 @@ private List _findPotentialFactories(JavaType type, Class pr for (int i = 0; i < factoryCount; ++i) { if (key.equals(methodKeys[i])) { result.set(i, - constructFactoryCreator(candidates.get(i), - typeResCtxt, mixinFactory)); + constructFactoryCreator(candidates.get(i), mixinFactory)); break; } } @@ -262,8 +255,7 @@ private List _findPotentialFactories(JavaType type, Class pr AnnotatedMethod factory = result.get(i); if (factory == null) { result.set(i, - constructFactoryCreator(candidates.get(i), - typeResCtxt, null)); + constructFactoryCreator(candidates.get(i), null)); } } return result; @@ -335,19 +327,18 @@ protected AnnotatedConstructor constructNonDefaultConstructor(ClassUtil.Ctor cto collectAnnotations(ctor, mixin), resolvedAnnotations); } - protected AnnotatedMethod constructFactoryCreator(Method m, - TypeResolutionContext typeResCtxt, Method mixin) + protected AnnotatedMethod constructFactoryCreator(Method m, Method mixin) { final int paramCount = m.getParameterTypes().length; if (_intr == null) { // when annotation processing is disabled - return new AnnotatedMethod(typeResCtxt, m, _emptyAnnotationMap(), + return new AnnotatedMethod(_typeContext, m, _emptyAnnotationMap(), _emptyAnnotationMaps(paramCount)); } if (paramCount == 0) { // common enough we can slightly optimize - return new AnnotatedMethod(typeResCtxt, m, collectAnnotations(m, mixin), + return new AnnotatedMethod(_typeContext, m, collectAnnotations(m, mixin), NO_ANNOTATION_MAPS); } - return new AnnotatedMethod(typeResCtxt, m, collectAnnotations(m, mixin), + return new AnnotatedMethod(_typeContext, m, collectAnnotations(m, mixin), collectAnnotations(m.getParameterAnnotations(), (mixin == null) ? null : mixin.getParameterAnnotations())); } diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/TypeResolutionContext.java b/src/main/java/com/fasterxml/jackson/databind/introspect/TypeResolutionContext.java index b250b6c876..405a5e9c21 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/TypeResolutionContext.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/TypeResolutionContext.java @@ -44,25 +44,4 @@ public String toString() { } */ } - - /** - * Dummy implementation for case where there are no bindings available - * (for example, for static methods and fields) - * - * @since 2.11.3 - */ - public static class Empty - implements TypeResolutionContext - { - private final TypeFactory _typeFactory; - - public Empty(TypeFactory tf) { - _typeFactory = tf; - } - - @Override - public JavaType resolveType(Type type) { - return _typeFactory.constructType(type); - } - } } diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/GenericTypeSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/GenericTypeSerializationTest.java index 47aaa9269b..bd41b3fe6d 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ser/GenericTypeSerializationTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ser/GenericTypeSerializationTest.java @@ -8,6 +8,9 @@ import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.GenericTypeSerializationTest.WrapperWithFactoryMethod.Value; + +import static java.util.Objects.requireNonNull; public class GenericTypeSerializationTest extends BaseMapTest { @@ -164,6 +167,74 @@ public static Attributes2821 dummyMethod(Map attributes) { } } + public static class WrapperWithFactoryMethod { + private final List values; + + private WrapperWithFactoryMethod(List values) { + this.values = requireNonNull(values, "values is null"); + } + + @JsonProperty + public List getValues() { + return values; + } + + @JsonCreator + public static WrapperWithFactoryMethod fromValues(@JsonProperty("values") List values) { + return new WrapperWithFactoryMethod<>(values); + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + WrapperWithFactoryMethod wrapper = (WrapperWithFactoryMethod) o; + return Objects.equals(values, wrapper.values); + } + + @Override + public int hashCode() { + return Objects.hash(values); + } + + @Override + public String toString() { + return values.toString(); + } + + public static class Value { + public int x; + + @JsonCreator + public Value(@JsonProperty("x") int x) { + this.x = x; + } + + @JsonProperty + public int getX() { + return x; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + Value rawValue = (Value) o; + return x == rawValue.x; + } + + @Override + public int hashCode() { + return Objects.hash(x); + } + + @Override + public String toString() { + return String.valueOf(x); + } + } + } + /* /********************************************************** /* Unit tests @@ -259,4 +330,11 @@ public void testTypeResolution2821() throws Exception String json = MAPPER.writeValueAsString(val); assertNotNull(json); } + + public void testTypeResolutionFactoryMethod() throws Exception + { + WrapperWithFactoryMethod src = new WrapperWithFactoryMethod<>(Arrays.asList(new Value(1), new Value(2))); + WrapperWithFactoryMethod output = MAPPER.readValue(MAPPER.writeValueAsString(src), new TypeReference>() {}); + assertEquals(src, output); + } }