Skip to content

Commit 45b5eb9

Browse files
committed
Merge branch '2.19'
2 parents 2f28183 + ec24929 commit 45b5eb9

File tree

5 files changed

+74
-6
lines changed

5 files changed

+74
-6
lines changed

release-notes/CREDITS-2.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,11 @@ Stanislav Shcherbakov (@glorrian)
18651865
* Contributed #4844: Fix wrapped array hanlding wrt `null` by `StdDeserializer`
18661866
(2.18.3)
18671867

1868+
Tomáš Poledný (@Saljack)
1869+
* Reported #4860: `ConstructorDetector.USE_PROPERTIES_BASED` does not work with
1870+
multiple constructors since 2.18
1871+
(2.18.3)
1872+
18681873
Liam Feid (@fxshlein)
18691874
* Contributed #1467: Support `@JsonUnwrapped` with `@JsonCreator`
18701875
(2.19.0)

release-notes/VERSION-2.x

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ Project: jackson-databind
4343
(fix by Joo-Hyuk K)
4444
#4844: Fix wrapped array handling wrt `null` by `StdDeserializer`
4545
(fix by Stanislav S)
46+
#4860: `ConstructorDetector.USE_PROPERTIES_BASED` does not work with
47+
multiple constructors since 2.18
48+
(reported by Tomáš P)
49+
(fix by Joo-Hyuk K, @cowtowncoder)
4650

4751
2.18.2 (27-Nov-2024)
4852

src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ private void _addSelectedPropertiesBasedCreator(DeserializationContext ctxt,
495495
if ((name == null) && (injectId == null)) {
496496
ctxt.reportBadTypeDefinition(beanDesc,
497497
"Argument #%d of Creator %s has no property name (and is not Injectable): can not use as property-based Creator",
498-
i, candidate);
498+
i, candidate);
499499
}
500500
}
501501
properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);

src/main/java/tools/jackson/databind/introspect/POJOPropertiesCollector.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,7 @@ protected void _addCreators(Map<String, POJOPropertyBuilder> props)
659659
}
660660

661661
// One more thing: if neither explicit (constructor or factory) nor
662-
// canonical (constructor?), consider implicit Constructor with
663-
// all named.
662+
// canonical (constructor?), consider implicit Constructor with all named.
664663
final ConstructorDetector ctorDetector = _config.getConstructorDetector();
665664
if (!creators.hasPropertiesBasedOrDelegating()
666665
&& !ctorDetector.requireCtorAnnotation()) {
@@ -963,10 +962,17 @@ private boolean _addImplicitConstructor(PotentialCreators collector,
963962
if (ctorDetector.singleArgCreatorDefaultsToDelegating()) {
964963
return false;
965964
}
965+
// 20-Dec-2024, tatu: [databind#4860] Cannot detect as properties-based
966+
// without implicit name (Injectable was checked earlier)
967+
String implicitParamName = ctor.implicitNameSimple(0);
968+
if (implicitParamName == null) {
969+
return false;
970+
}
971+
966972
// if not, prefer Properties-based if explicit preference OR
967973
// property with same name with at least one visible accessor
968974
if (!ctorDetector.singleArgCreatorDefaultsToProperties()) {
969-
POJOPropertyBuilder prop = props.get(ctor.implicitNameSimple(0));
975+
POJOPropertyBuilder prop = props.get(implicitParamName);
970976
if ((prop == null) || !prop.anyVisible() || prop.anyIgnorals()) {
971977
return false;
972978
}

src/test/java/tools/jackson/databind/deser/creators/ConstructorDetectorTest.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.junit.jupiter.api.Test;
44

55
import com.fasterxml.jackson.annotation.JsonCreator;
6+
7+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
68
import com.fasterxml.jackson.annotation.Nulls;
79

810
import tools.jackson.databind.*;
@@ -16,7 +18,7 @@
1618
import static org.junit.jupiter.api.Assertions.assertEquals;
1719
import static org.junit.jupiter.api.Assertions.fail;
1820

19-
// Tests for [databind#1498], [databind#3241] (Jackson 2.12)
21+
// Tests for [databind#1498], [databind#3241]
2022
public class ConstructorDetectorTest extends DatabindTestUtil
2123
{
2224
static class SingleArgNotAnnotated {
@@ -138,9 +140,24 @@ public Boolean field() {
138140
return field;
139141
}
140142
}
141-
143+
144+
// [databind#4860]
145+
@JsonPropertyOrder({ "id", "name "})
146+
static class Foo4860 {
147+
public String id;
148+
public String name;
149+
150+
public Foo4860() { }
151+
152+
public Foo4860(String id) {
153+
// should not be called as of Jackson 2.x
154+
throw new IllegalStateException("Should not auto-detect args-taking constructor");
155+
}
156+
}
157+
142158
private final ObjectMapper MAPPER_PROPS = mapperFor(ConstructorDetector.USE_PROPERTIES_BASED);
143159
private final ObjectMapper MAPPER_DELEGATING = mapperFor(ConstructorDetector.USE_DELEGATING);
160+
private final ObjectMapper MAPPER_DEFAULT = mapperFor(ConstructorDetector.DEFAULT);
144161
private final ObjectMapper MAPPER_EXPLICIT = mapperFor(ConstructorDetector.EXPLICIT_ONLY);
145162

146163
private final ObjectMapper MAPPER_MUST_ANNOTATE = mapperFor(ConstructorDetector.DEFAULT
@@ -379,6 +396,42 @@ void nullHandlingCreator3241() throws Exception {
379396
}
380397
}
381398

399+
// [databind#4860]
400+
@Test
401+
public void testDeserialization4860PropsBased() throws Exception {
402+
_test4680With(MAPPER_PROPS);
403+
}
404+
405+
@Test
406+
public void testDeserialization4860Delegating() throws Exception {
407+
_test4680With(MAPPER_DELEGATING);
408+
}
409+
410+
@Test
411+
public void testDeserialization4860Default() throws Exception {
412+
_test4680With(MAPPER_DEFAULT);
413+
}
414+
415+
@Test
416+
public void testDeserialization4860Explicit() throws Exception {
417+
_test4680With(MAPPER_EXPLICIT);
418+
}
419+
420+
private void _test4680With(ObjectMapper mapper) throws Exception
421+
{
422+
_test4680With(mapper, "{}", a2q("{'id':null,'name':null}"));
423+
_test4680With(mapper, a2q("{'id':'something'}"),
424+
a2q("{'id':'something','name':null}"));
425+
_test4680With(mapper, a2q("{'id':'something','name':'name'}"),
426+
a2q("{'id':'something','name':'name'}"));
427+
}
428+
429+
private void _test4680With(ObjectMapper mapper, String input, String output) throws Exception
430+
{
431+
Foo4860 result = mapper.readValue(input, Foo4860.class);
432+
assertEquals(output, mapper.writeValueAsString(result));
433+
}
434+
382435
/*
383436
/**********************************************************************
384437
/* Helper methods

0 commit comments

Comments
 (0)