From f8a9932102a192760763f78bb90200e10c7a1a47 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Sat, 28 Sep 2024 19:11:01 +0900 Subject: [PATCH 1/6] Add fix in GetParameter() and hasParameter() in PropertyValueBuffer --- .../deser/impl/PropertyValueBuffer.java | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index 531c6ab24e..c83142b771 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -5,9 +5,11 @@ import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; +import com.fasterxml.jackson.databind.exc.ValueInstantiationException; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** @@ -135,6 +137,11 @@ public PropertyValueBuffer(JsonParser p, DeserializationContext ctxt, int paramC */ public final boolean hasParameter(SettableBeanProperty prop) { + if (_anyParamSetter != null) { + if (prop.getCreatorIndex() == _anyParamSetter.getParameterIndex()) { + return true; + } + } if (_paramsSeenBig == null) { return ((_paramsSeen >> prop.getCreatorIndex()) & 1) == 1; } @@ -160,6 +167,16 @@ public Object getParameter(SettableBeanProperty prop) } else { value = _creatorParameters[prop.getCreatorIndex()] = _findMissing(prop); } + // 28-Sep-2024 : [databind#4508] Support any-setter flowing through creator + if ((value == null) && (_anyParamSetter != null ) + && (prop.getCreatorIndex() == _anyParamSetter.getParameterIndex())) { + try { + value = _createAndSetAnySetterValue(); + } catch (IOException e) { + // do-nothing here? + throw JsonMappingException.fromUnexpectedIOE(e); + } + } if (value == null && _context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { return _context.reportInputMismatch(prop, "Null value for creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES` enabled", @@ -198,11 +215,7 @@ public Object[] getParameters(SettableBeanProperty[] props) } // [databind#562] since 2.18 : Respect @JsonAnySetter in @JsonCreator if (_anyParamSetter != null) { - Object anySetterParameterObject = _anyParamSetter.createParameterObject(); - for (PropertyValue pv = _anyParamBuffered; pv != null; pv = pv.next) { - pv.setValue(anySetterParameterObject); - } - _creatorParameters[_anyParamSetter.getParameterIndex()] = anySetterParameterObject; + _creatorParameters[_anyParamSetter.getParameterIndex()] = _createAndSetAnySetterValue(); } if (_context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { for (int ix = 0; ix < props.length; ++ix) { @@ -217,6 +230,20 @@ public Object[] getParameters(SettableBeanProperty[] props) return _creatorParameters; } + /** + * Helper method called to create and set any values buffered for "any setter" + * + * @since 2.18 + */ + private Object _createAndSetAnySetterValue() throws IOException + { + Object anySetterParameterObject = _anyParamSetter.createParameterObject(); + for (PropertyValue pv = _anyParamBuffered; pv != null; pv = pv.next) { + pv.setValue(anySetterParameterObject); + } + return anySetterParameterObject; + } + protected Object _findMissing(SettableBeanProperty prop) throws JsonMappingException { // 08-Jun-2024: [databind#562] AnySetters are bit special From 215d0198e1980ca8b776f3990a0dcc53c8c2e3d7 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Sun, 29 Sep 2024 00:12:24 +0900 Subject: [PATCH 2/6] Add comment to new code --- .../jackson/databind/deser/impl/PropertyValueBuffer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index c83142b771..45ae4bd044 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -137,6 +137,7 @@ public PropertyValueBuffer(JsonParser p, DeserializationContext ctxt, int paramC */ public final boolean hasParameter(SettableBeanProperty prop) { + // 28-Sep-2024 : [databind#4508] Support any-setter flowing through creator if (_anyParamSetter != null) { if (prop.getCreatorIndex() == _anyParamSetter.getParameterIndex()) { return true; From c4e870c9f3886af6097dc7b60b4770e90cf6fb89 Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Sun, 29 Sep 2024 00:17:54 +0900 Subject: [PATCH 3/6] Add credits in case we push thru --- release-notes/VERSION-2.x | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 8c74695818..11644a8f18 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -81,6 +81,9 @@ Project: jackson-databind (contributed by @pjfanning) #4709: Add `JacksonCollectors` with `toArrayNode()` implementation (contributed by @rikkarth) +#4508: Deserialized JsonAnySetter field in Kotlin data class is null #4508 + (reported by @MaximValeev) + (fix by Joo-Hyuk K) 2.17.2 (05-Jul-2024) From 3a13eacee5aa323d46ffb24014a14532e2cc006a Mon Sep 17 00:00:00 2001 From: "Kim, Joo Hyuk" Date: Sun, 29 Sep 2024 09:36:08 +0900 Subject: [PATCH 4/6] Fix up docs --- release-notes/VERSION-2.x | 9 ++++++--- .../jackson/databind/deser/impl/PropertyValueBuffer.java | 2 -- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 11644a8f18..7f00c460e9 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -4,6 +4,12 @@ Project: jackson-databind === Releases === ------------------------------------------------------------------------ +2.18.1 (WIP-2024) + +#4508: Deserialized JsonAnySetter field in Kotlin data class is null #4508 + (reported by @MaximValeev) + (fix by Joo-Hyuk K) + 2.18.0 (26-Sep-2024) #562: Allow `@JsonAnySetter` to flow through Creators @@ -81,9 +87,6 @@ Project: jackson-databind (contributed by @pjfanning) #4709: Add `JacksonCollectors` with `toArrayNode()` implementation (contributed by @rikkarth) -#4508: Deserialized JsonAnySetter field in Kotlin data class is null #4508 - (reported by @MaximValeev) - (fix by Joo-Hyuk K) 2.17.2 (05-Jul-2024) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index 45ae4bd044..dc71933c4b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -233,8 +233,6 @@ public Object[] getParameters(SettableBeanProperty[] props) /** * Helper method called to create and set any values buffered for "any setter" - * - * @since 2.18 */ private Object _createAndSetAnySetterValue() throws IOException { From e84269956d3596be0782e6d3e62925542da7a5c5 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 28 Sep 2024 20:55:31 -0700 Subject: [PATCH 5/6] Minor streamlining --- .../deser/impl/PropertyValueBuffer.java | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index dc71933c4b..31d2b76bd3 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -5,11 +5,9 @@ import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.SettableAnyProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; -import com.fasterxml.jackson.databind.exc.ValueInstantiationException; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; /** @@ -137,16 +135,24 @@ public PropertyValueBuffer(JsonParser p, DeserializationContext ctxt, int paramC */ public final boolean hasParameter(SettableBeanProperty prop) { + final int ix = prop.getCreatorIndex(); + + if (_paramsSeenBig == null) { + if (((_paramsSeen >> ix) & 1) == 1) { + return true; + } + } else { + if (_paramsSeenBig.get(ix)) { + return true; + } + } // 28-Sep-2024 : [databind#4508] Support any-setter flowing through creator if (_anyParamSetter != null) { - if (prop.getCreatorIndex() == _anyParamSetter.getParameterIndex()) { + if (ix == _anyParamSetter.getParameterIndex()) { return true; } } - if (_paramsSeenBig == null) { - return ((_paramsSeen >> prop.getCreatorIndex()) & 1) == 1; - } - return _paramsSeenBig.get(prop.getCreatorIndex()); + return false; } /** @@ -171,12 +177,7 @@ public Object getParameter(SettableBeanProperty prop) // 28-Sep-2024 : [databind#4508] Support any-setter flowing through creator if ((value == null) && (_anyParamSetter != null ) && (prop.getCreatorIndex() == _anyParamSetter.getParameterIndex())) { - try { - value = _createAndSetAnySetterValue(); - } catch (IOException e) { - // do-nothing here? - throw JsonMappingException.fromUnexpectedIOE(e); - } + value = _createAndSetAnySetterValue(); } if (value == null && _context.isEnabled(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES)) { return _context.reportInputMismatch(prop, @@ -234,11 +235,20 @@ public Object[] getParameters(SettableBeanProperty[] props) /** * Helper method called to create and set any values buffered for "any setter" */ - private Object _createAndSetAnySetterValue() throws IOException + private Object _createAndSetAnySetterValue() throws JsonMappingException { Object anySetterParameterObject = _anyParamSetter.createParameterObject(); for (PropertyValue pv = _anyParamBuffered; pv != null; pv = pv.next) { - pv.setValue(anySetterParameterObject); + try { + pv.setValue(anySetterParameterObject); + + // Since one of callers only exposes JsonMappingException, but pv.setValue() + // nominally leaks IOException, need to do this unfortunate conversion + } catch (JsonMappingException e) { + throw e; + } catch (IOException e) { + throw JsonMappingException.fromUnexpectedIOE(e); + } } return anySetterParameterObject; } From 6cc443c680e4d844aea203000186d584f307efc3 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 28 Sep 2024 21:00:45 -0700 Subject: [PATCH 6/6] Update release notes --- release-notes/CREDITS-2.x | 3 +++ release-notes/VERSION-2.x | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 42dad748c5..6803c37e17 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -1834,3 +1834,6 @@ Rikkarth (rikkarth@github) * Contributed #4709: Add `JacksonCollectors` with `toArrayNode()` implementation (2.18.0) +Maxim Valeev (@MaximValeev) + * Reported #4508: Deserialized JsonAnySetter field in Kotlin data class is null + (2.18.1) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 7f00c460e9..c9097a2c05 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -6,7 +6,7 @@ Project: jackson-databind 2.18.1 (WIP-2024) -#4508: Deserialized JsonAnySetter field in Kotlin data class is null #4508 +#4508: Deserialized JsonAnySetter field in Kotlin data class is null (reported by @MaximValeev) (fix by Joo-Hyuk K)