From 308228ba634aae8f5945315fccf1ce13f21c0989 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Mon, 7 Oct 2024 23:33:06 +0900 Subject: [PATCH 1/3] Fix implementation --- .../databind/deser/BeanDeserializer.java | 7 ++- .../databind/deser/SettableAnyProperty.java | 7 +++ ...nySetterFieldWithCreatorDeser4639Test.java | 60 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/JsonAnySetterFieldWithCreatorDeser4639Test.java diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java index f7f5bb1ca4..e9b2481afb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java @@ -505,7 +505,12 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri // "any property"? if (_anySetter != null) { try { - buffer.bufferAnyParameterProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); + // [databind#4639] Since 2.18.1 AnySetter might not part of the creator, but just some field. + if (_anySetter.isFieldType()) { + buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); + } else { + buffer.bufferAnyParameterProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); + } } catch (Exception e) { wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java index 0cb738ada7..d3433b1dc9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java @@ -203,6 +203,13 @@ public Object createParameterObject() { throw new UnsupportedOperationException("Cannot call createParameterObject() on " + getClass().getName()); } + /** + * Method called to check whether this property is field + * + * @since 2.18.1 + */ + public boolean isFieldType() { return _setterIsField; } + /* /********************************************************** /* Public API, deserialization diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/JsonAnySetterFieldWithCreatorDeser4639Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/JsonAnySetterFieldWithCreatorDeser4639Test.java new file mode 100644 index 0000000000..bea1dca1e7 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/JsonAnySetterFieldWithCreatorDeser4639Test.java @@ -0,0 +1,60 @@ +package com.fasterxml.jackson.databind.deser; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +// [databind#4639] 2.18.1 : regression when using @JsonAnySetter outside of @JsonCreator +public class JsonAnySetterFieldWithCreatorDeser4639Test + extends DatabindTestUtil +{ + + public static class Bean { + private int b; + private int d; + + @JsonAnySetter + private Map any; + + @JsonCreator + public Bean(@JsonProperty("b") int b, @JsonProperty("d") int d) { + this.b = b; + this.d = d; + } + } + + @Test + public void testJsonAnySetter() + throws Exception + { + String json = "{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5,\"f\":6}"; + + Bean bean = newJsonMapper().readValue(json, Bean.class); + assertEquals(2, bean.b); + assertEquals(4, bean.d); + + // failed with: + // org.opentest4j.AssertionFailedError: + // Expected :{b=2, c=3, e=5, f=6} + // Actual :{e=5, f=6} + assertEquals(mapOf("a", 1, "c", 3, "e", 5, "f", 6), bean.any); + } + + private Map mapOf(String a, int i, String b, int i1, String c, int i2, String d, int i3) + { + Map map = new java.util.HashMap<>(); + map.put(a, i); + map.put(b, i1); + map.put(c, i2); + map.put(d, i3); + return map; + } + +} From 8ceccd85b7a12f83f763324d93045355613231ab Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Wed, 9 Oct 2024 17:14:57 +0900 Subject: [PATCH 2/3] Add credit --- release-notes/VERSION-2.x | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index a21fe25dc5..404f5946f9 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -13,6 +13,10 @@ Project: jackson-databind #4724: Deserialization behavior change with Records, `@JsonCreator` and `@JsonValue` between 2.17 and 2.18 (reported by Antti L) +#4639: @JsonAnySetter on field ignoring unrecognized properties if they are + declared before the last recognized properties in JSON + (reported by Sim Y-T) + (fix by Joo-Hyuk K) 2.18.0 (26-Sep-2024) From 4f15cf15ffbf505add86805e53f5b4432e74470d Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 9 Oct 2024 20:45:26 -0700 Subject: [PATCH 3/3] Minor reordering --- release-notes/VERSION-2.x | 8 ++++---- .../databind/deser/SettableAnyProperty.java | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 404f5946f9..f50090dcef 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -9,14 +9,14 @@ Project: jackson-databind #4508: Deserialized JsonAnySetter field in Kotlin data class is null (reported by @MaximValeev) (fix by Joo-Hyuk K) -#4718: Should not fail on trying to serialize `java.time.DateTimeException` -#4724: Deserialization behavior change with Records, `@JsonCreator` and - `@JsonValue` between 2.17 and 2.18 - (reported by Antti L) #4639: @JsonAnySetter on field ignoring unrecognized properties if they are declared before the last recognized properties in JSON (reported by Sim Y-T) (fix by Joo-Hyuk K) +#4718: Should not fail on trying to serialize `java.time.DateTimeException` +#4724: Deserialization behavior change with Records, `@JsonCreator` and + `@JsonValue` between 2.17 and 2.18 + (reported by Antti L) 2.18.0 (26-Sep-2024) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java index d3433b1dc9..11998275f4 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java @@ -194,6 +194,13 @@ Object readResolve() { */ public int getParameterIndex() { return -1; } + /** + * Method called to check whether this property is field + * + * @since 2.18.1 + */ + public boolean isFieldType() { return _setterIsField; } + /** * Create an instance of value to pass through Creator parameter. * @@ -203,13 +210,6 @@ public Object createParameterObject() { throw new UnsupportedOperationException("Cannot call createParameterObject() on " + getClass().getName()); } - /** - * Method called to check whether this property is field - * - * @since 2.18.1 - */ - public boolean isFieldType() { return _setterIsField; } - /* /********************************************************** /* Public API, deserialization