Skip to content

Commit ec24929

Browse files
committed
Merge branch '2.18' into 2.19
2 parents 18d4874 + 7d94c2f commit ec24929

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
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/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ private void _addSelectedPropertiesBasedCreator(DeserializationContext ctxt,
534534
if ((name == null) && (injectId == null)) {
535535
ctxt.reportBadTypeDefinition(beanDesc,
536536
"Argument #%d of Creator %s has no property name (and is not Injectable): can not use as property-based Creator",
537-
i, candidate);
537+
i, candidate);
538538
}
539539
}
540540
properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

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

713713
// One more thing: if neither explicit (constructor or factory) nor
714-
// canonical (constructor?), consider implicit Constructor with
715-
// all named.
714+
// canonical (constructor?), consider implicit Constructor with all named.
716715
final ConstructorDetector ctorDetector = _config.getConstructorDetector();
717716
if (!creators.hasPropertiesBasedOrDelegating()
718717
&& !ctorDetector.requireCtorAnnotation()) {
@@ -1009,10 +1008,17 @@ private boolean _addImplicitConstructor(PotentialCreators collector,
10091008
if (ctorDetector.singleArgCreatorDefaultsToDelegating()) {
10101009
return false;
10111010
}
1011+
// 20-Dec-2024, tatu: [databind#4860] Cannot detect as properties-based
1012+
// without implicit name (Injectable was checked earlier)
1013+
String implicitParamName = ctor.implicitNameSimple(0);
1014+
if (implicitParamName == null) {
1015+
return false;
1016+
}
1017+
10121018
// if not, prefer Properties-based if explicit preference OR
10131019
// property with same name with at least one visible accessor
10141020
if (!ctorDetector.singleArgCreatorDefaultsToProperties()) {
1015-
POJOPropertyBuilder prop = props.get(ctor.implicitNameSimple(0));
1021+
POJOPropertyBuilder prop = props.get(implicitParamName);
10161022
if ((prop == null) || !prop.anyVisible() || prop.anyIgnorals()) {
10171023
return false;
10181024
}

src/test/java/com/fasterxml/jackson/databind/deser/creators/ConstructorDetectorTest.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.junit.jupiter.api.Test;
44

55
import com.fasterxml.jackson.annotation.JsonCreator;
6+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
67
import com.fasterxml.jackson.annotation.JsonSetter;
78
import com.fasterxml.jackson.annotation.Nulls;
89

@@ -139,9 +140,24 @@ public Boolean field() {
139140
return field;
140141
}
141142
}
142-
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+
143158
private final ObjectMapper MAPPER_PROPS = mapperFor(ConstructorDetector.USE_PROPERTIES_BASED);
144159
private final ObjectMapper MAPPER_DELEGATING = mapperFor(ConstructorDetector.USE_DELEGATING);
160+
private final ObjectMapper MAPPER_DEFAULT = mapperFor(ConstructorDetector.DEFAULT);
145161
private final ObjectMapper MAPPER_EXPLICIT = mapperFor(ConstructorDetector.EXPLICIT_ONLY);
146162

147163
private final ObjectMapper MAPPER_MUST_ANNOTATE = mapperFor(ConstructorDetector.DEFAULT
@@ -379,6 +395,42 @@ void nullHandlingCreator3241() throws Exception {
379395
}
380396
}
381397

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

0 commit comments

Comments
 (0)