From 492fb802380f38ea3a5a31446bc53cb895cca029 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 24 Feb 2021 16:09:10 -0800 Subject: [PATCH] Fixed #3062 --- release-notes/VERSION-2.x | 2 ++ .../databind/deser/impl/CreatorCollector.java | 31 +++++++++++++------ .../deser/creators/SingleArgCreatorTest.java | 31 +++++++++++++++++-- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 7474fedc2b..1c8adb1537 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -28,6 +28,8 @@ Project: jackson-databind `com.fasterxml.jackson.databind.node.ObjectNode` out of VALUE_NULL token (reported by Stexxen@github) #3060: Missing override for `hasAsKey()` in `AnnotationIntrospectorPair` +#3062: Creator lookup fails with `InvalidDefinitionException` for conflict + between single-double/single-Double arg constructor 2.12.1 (08-Jan-2021) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java index 8eed4eb74b..9bf9fe4a88 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java @@ -13,10 +13,10 @@ /** * Container class for storing information on creators (based on annotations, - * visibility), to be able to build actual instantiator later on. + * visibility), to be able to build actual {@code ValueInstantiator} later on. */ -public class CreatorCollector { - // Since 2.5 +public class CreatorCollector +{ protected final static int C_DEFAULT = 0; protected final static int C_STRING = 1; protected final static int C_INT = 2; @@ -34,22 +34,24 @@ public class CreatorCollector { "from-big-decimal", "from-boolean", "delegate", "property-based", "array-delegate" }; - // Type of bean being created - final protected BeanDescription _beanDesc; + /** + * Type of bean being created + */ + protected final BeanDescription _beanDesc; - final protected boolean _canFixAccess; + protected final boolean _canFixAccess; /** * @since 2.7 */ - final protected boolean _forceAccess; + protected final boolean _forceAccess; /** * Set of creators we have collected so far * * @since 2.5 */ - final protected AnnotatedWithParams[] _creators = new AnnotatedWithParams[11]; + protected final AnnotatedWithParams[] _creators = new AnnotatedWithParams[11]; /** * Bitmask of creators that were explicitly marked as creators; false for @@ -304,7 +306,8 @@ protected boolean verifyNonDup(AnnotatedWithParams newOne, int typeIndex, boolea // one more thing: ok to override in sub-class // 23-Feb-2021, tatu: Second check is for case of static factory vs constructor, - // which is handled by caller, presumable. Removing it would fail one test + // which is handled by caller, presumably. + // Removing it would fail one test (in case interested). if (verify && (oldOne.getClass() == newOne.getClass())) { // [databind#667]: avoid one particular class of bogus problems final Class oldType = oldOne.getRawParameterType(0); @@ -330,6 +333,16 @@ else if (newType.isAssignableFrom(oldType)) { } else if (oldType.isAssignableFrom(newType)) { // new type more specific, use it ; + // 23-Feb-2021, tatu: due to [databind#3062], backwards-compatibility, + // let's allow "primitive/Wrapper" case and tie-break in favor + // of PRIMITIVE argument (null would never map to scalar creators, + // and fundamentally all we need is a tie-breaker: up to caller to + // annotate if wants the wrapper one) + } else if (oldType.isPrimitive() != newType.isPrimitive()) { + // Prefer primitive one + if (oldType.isPrimitive()) { + return false; + } } else { // 02-May-2020, tatu: Should this only result in exception if both // explicit? Doing so could lead to arbitrary choice between diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/SingleArgCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/SingleArgCreatorTest.java index f04bb50d80..c357a2de89 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/SingleArgCreatorTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/SingleArgCreatorTest.java @@ -1,6 +1,10 @@ package com.fasterxml.jackson.databind.deser.creators; +import java.util.Arrays; +import java.util.List; + import com.fasterxml.jackson.annotation.*; + import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; @@ -138,13 +142,25 @@ public static SingleArgWithImplicit from(XY v) { public XY getFoobar() { return _value; } } + // [databind#3062] + static class DecVector3062 { + List elems; + + public DecVector3062() { super(); } + public DecVector3062(List e) { elems = e; } + public DecVector3062(double elem) { elems = Arrays.asList(elem); } + public DecVector3062(Double elem) { elems = Arrays.asList(elem); } + + public List getElems() { return elems; } + } + /* - /********************************************************** + /********************************************************************** /* Test methods - /********************************************************** + /********************************************************************** */ - private final ObjectMapper MAPPER = objectMapper(); + private final ObjectMapper MAPPER = newJsonMapper(); public void testNamedSingleArg() throws Exception { @@ -206,4 +222,13 @@ public void testSingleImplicitDelegating() throws Exception assertEquals(1, v.x); assertEquals(2, v.y); } + + // [databind#3062] + public void testMultipleDoubleCreators3062() throws Exception + { + DecVector3062 vector = new DecVector3062(Arrays.asList(1.0, 2.0, 3.0)); + String result = MAPPER.writeValueAsString(vector); + DecVector3062 deser = MAPPER.readValue(result, DecVector3062.class); + assertEquals(vector.elems, deser.elems); + } }