Skip to content

Commit fd80718

Browse files
authored
Fix #4602: handling of Array-delegating Creator (#4609)
1 parent 8a42895 commit fd80718

File tree

5 files changed

+40
-6
lines changed

5 files changed

+40
-6
lines changed

release-notes/CREDITS-2.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,3 +1812,8 @@ Alexandre Jacob (ajacob@github)
18121812
* Reported #4545: Unexpected deserialization behavior with `@JsonCreator`,
18131813
`@JsonProperty` and javac `-parameters`
18141814
(2.18.0)
1815+
1816+
Eduard Gomoliako (Gems@github)
1817+
* Reported #4602: Possible wrong use of _arrayDelegateDeserializer in
1818+
BeanDeserializerBase::deserializeFromObjectUsingNonDefault()
1819+
(2.18.0)

release-notes/VERSION-2.x

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ Project: jackson-databind
5050
#4570: Deprecate `ObjectMapper.canDeserialize()`/`ObjectMapper.canSerialize()`
5151
#4580: Add `MapperFeature.SORT_CREATOR_PROPERTIES_BY_DECLARATION_ORDER` to use
5252
Creator properties' declaration order for sorting
53+
#4602: Possible wrong use of _arrayDelegateDeserializer in
54+
BeanDeserializerBase::deserializeFromObjectUsingNonDefault()
55+
(reported by Eduard G)
5356

5457
2.17.2 (not yet released)
5558

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,7 +1482,9 @@ protected Object deserializeFromObjectId(JsonParser p, DeserializationContext ct
14821482
protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
14831483
DeserializationContext ctxt) throws IOException
14841484
{
1485-
final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1485+
// 02-Jul-2024, tatu: [databind#4602] Need to tweak regular and "array" delegating
1486+
// Creator handling
1487+
final JsonDeserializer<Object> delegateDeser = _delegateDeserializer(p);
14861488
if (delegateDeser != null) {
14871489
final Object bean = _valueInstantiator.createUsingDelegate(ctxt,
14881490
delegateDeser.deserialize(p, ctxt));
@@ -1505,7 +1507,7 @@ protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
15051507
// 01-May-2022, tatu: [databind#3417] special handling for (Graal) native images
15061508
if (NativeImageUtil.needsReflectionConfiguration(raw)) {
15071509
return ctxt.handleMissingInstantiator(raw, null, p,
1508-
"cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized");
1510+
"cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized");
15091511
}
15101512
return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
15111513
"cannot deserialize from Object value (no delegate- or property-based Creator)");
@@ -1710,6 +1712,30 @@ protected final JsonDeserializer<Object> _delegateDeserializer() {
17101712
return deser;
17111713
}
17121714

1715+
/**
1716+
* Alternate to {@link #_delegateDeserializer()} which will only consider
1717+
* {@code _arrayDelegateDeserializer} if given {@link JsonParser} points to
1718+
* {@link JsonToken#START_ARRAY} token.
1719+
*
1720+
* @since 2.18
1721+
*/
1722+
protected final JsonDeserializer<Object> _delegateDeserializer(JsonParser p) {
1723+
if (_delegateDeserializer == null) {
1724+
// Note! Will not call `JsonParser.isExpectedArrayToken()` as that could
1725+
// "transform" `JsonToken.START_OBJECT` into `JsonToken.START_ARRAY` and
1726+
// here there is no strong expectation of Array value
1727+
if (_arrayDelegateDeserializer != null) {
1728+
// Alas, need bit elaborate logic: either JSON Array, OR no
1729+
// Properties-based Creator
1730+
if (p.hasToken(JsonToken.START_ARRAY)
1731+
|| (_propertyBasedCreator == null)) {
1732+
return _arrayDelegateDeserializer;
1733+
}
1734+
}
1735+
}
1736+
return _delegateDeserializer;
1737+
}
1738+
17131739
/*
17141740
/**********************************************************
17151741
/* Overridable helper methods

src/test/java/com/fasterxml/jackson/failing/TwoCreators4602Test.java renamed to src/test/java/com/fasterxml/jackson/databind/deser/creators/TwoCreators4602Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.failing;
1+
package com.fasterxml.jackson.databind.deser.creators;
22

33
import com.fasterxml.jackson.annotation.JsonCreator;
44
import com.fasterxml.jackson.annotation.JsonProperty;

src/test/java/com/fasterxml/jackson/databind/struct/SingleValueAsArrayTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
public class SingleValueAsArrayTest extends DatabindTestUtil
2121
{
22-
private static final String JSON = "[{\"message\":\"messageHere\"}]";
23-
2422
static class Bean1421A
2523
{
2624
List<Messages> bs = Collections.emptyList();
@@ -77,8 +75,10 @@ public Bean1421B(T value) {
7775
@Test
7876
public void testSuccessfulDeserializationOfObjectWithChainedArrayCreators() throws IOException
7977
{
80-
Bean1421A result = MAPPER.readValue(JSON, Bean1421A.class);
78+
Bean1421A result = MAPPER.readValue("[{\"message\":\"messageHere\"}]", Bean1421A.class);
8179
assertNotNull(result);
80+
assertNotNull(result.bs);
81+
assertEquals(1, result.bs.size());
8282
}
8383

8484
@Test

0 commit comments

Comments
 (0)