From f7fa567a7805a31d30b419197aacf839ab014798 Mon Sep 17 00:00:00 2001 From: Yih Tsern Date: Mon, 22 Jul 2024 08:20:17 +0800 Subject: [PATCH 1/3] Add Records+JsonAnySetter workarounds shared in #3439, as test cases. --- .../records/RecordWithJsonAnySetterTest.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java new file mode 100644 index 0000000000..3da385d0b0 --- /dev/null +++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java @@ -0,0 +1,110 @@ +package com.fasterxml.jackson.databind.records; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; +import org.junit.jupiter.api.Test; +import org.opentest4j.AssertionFailedError; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +public class RecordWithJsonAnySetterTest extends DatabindTestUtil { + + // Workaround mentioned in [databind#3439] + record RecordWorkaroundWithAnySetterMethodWithAltCtor(int id, Map any) { + @JsonCreator + public RecordWorkaroundWithAnySetterMethodWithAltCtor(@JsonProperty("id") int id) { + this(id, new LinkedHashMap<>()); + } + + @JsonAnySetter + private void updateProperty(String name, Object value) { + any.put(name, value); + } + } + + // Workaround mentioned in [databind#3439] + record RecordWorkaroundWithAnySetterMethodWithCanonCtor(int id, Map any) { + + RecordWorkaroundWithAnySetterMethodWithCanonCtor { + any = (any != null) ? any : new LinkedHashMap<>(); + } + + @JsonAnySetter + public void addAny(String name, Object value) { + any.put(name, value); + } + } + + // Workaround mentioned in [databind#3439] + record RecordWorkaroundWithAnySetterComponentAltCtor(int id, @JsonAnySetter Map any) { + @JsonCreator + public RecordWorkaroundWithAnySetterComponentAltCtor(@JsonProperty("id") int id) { + this(id, new LinkedHashMap<>()); + } + } + + // A proper one without workaround + record RecordWithAnySetterComponentCanonCtor(int id, @JsonAnySetter Map any) { + } + + private final ObjectMapper MAPPER = newJsonMapper(); + + @Test + public void testDeserializeWorkaround_WithAnySetterMethod_WithAltConstructor() throws Exception { + RecordWorkaroundWithAnySetterMethodWithAltCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterMethodWithAltCtor.class); + + Map expectedAny = new LinkedHashMap<>(); + expectedAny.put("any1", "Any 1"); + expectedAny.put("any2", "Any 2"); + assertEquals(new RecordWorkaroundWithAnySetterMethodWithAltCtor(123, expectedAny), value); + } + + @Test + public void testDeserializeWorkaround_WithAnySetterMethod_WithCanonicalConstructor() throws Exception { + RecordWorkaroundWithAnySetterMethodWithCanonCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterMethodWithCanonCtor.class); + + Map expectedAny = new LinkedHashMap<>(); + expectedAny.put("any1", "Any 1"); + expectedAny.put("any2", "Any 2"); + try { + assertEquals(new RecordWorkaroundWithAnySetterMethodWithCanonCtor(123, expectedAny), value); + fail("Used to fail, but is now working again"); + } catch (AssertionFailedError e) { + // Used to work, but stopped working starting from 2.18.0 due to [databind#4558] + verifyException(e, "[id=123, any={}]"); + } + } + + @Test + public void testDeserializeWorkaround_WithAnySetterComponent_WithAltConstructor() throws Exception { + try { + RecordWorkaroundWithAnySetterComponentAltCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterComponentAltCtor.class); + fail("Used to fail, but is now: " + value); + } catch (UnrecognizedPropertyException e) { + // Used to work, but stopped working starting from 2.15.0 due to [databind#3737] + verifyException(e, "Unrecognized field \"any1\""); + } + } + + @Test + public void testDeserialize_WithAnySetterComponent_WithCanonicalConstructor() throws Exception { + RecordWithAnySetterComponentCanonCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWithAnySetterComponentCanonCtor.class); + + Map expectedAny = new LinkedHashMap<>(); + expectedAny.put("any1", "Any 1"); + expectedAny.put("any2", "Any 2"); + assertEquals(new RecordWithAnySetterComponentCanonCtor(123, expectedAny), value); + } +} From 91f4b8fae76a59a37cc734f4e4baef52655dd999 Mon Sep 17 00:00:00 2001 From: Yih Tsern Date: Mon, 22 Jul 2024 10:11:31 +0800 Subject: [PATCH 2/3] Remove test cases for workarounds that are no longer working - we don't really care even if it somehow works again in the future. --- .../records/RecordWithJsonAnySetterTest.java | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java index 3da385d0b0..0996c66c33 100644 --- a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java +++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java @@ -4,16 +4,13 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; import org.junit.jupiter.api.Test; -import org.opentest4j.AssertionFailedError; import java.util.LinkedHashMap; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; public class RecordWithJsonAnySetterTest extends DatabindTestUtil { @@ -30,27 +27,6 @@ private void updateProperty(String name, Object value) { } } - // Workaround mentioned in [databind#3439] - record RecordWorkaroundWithAnySetterMethodWithCanonCtor(int id, Map any) { - - RecordWorkaroundWithAnySetterMethodWithCanonCtor { - any = (any != null) ? any : new LinkedHashMap<>(); - } - - @JsonAnySetter - public void addAny(String name, Object value) { - any.put(name, value); - } - } - - // Workaround mentioned in [databind#3439] - record RecordWorkaroundWithAnySetterComponentAltCtor(int id, @JsonAnySetter Map any) { - @JsonCreator - public RecordWorkaroundWithAnySetterComponentAltCtor(@JsonProperty("id") int id) { - this(id, new LinkedHashMap<>()); - } - } - // A proper one without workaround record RecordWithAnySetterComponentCanonCtor(int id, @JsonAnySetter Map any) { } @@ -68,35 +44,6 @@ public void testDeserializeWorkaround_WithAnySetterMethod_WithAltConstructor() t assertEquals(new RecordWorkaroundWithAnySetterMethodWithAltCtor(123, expectedAny), value); } - @Test - public void testDeserializeWorkaround_WithAnySetterMethod_WithCanonicalConstructor() throws Exception { - RecordWorkaroundWithAnySetterMethodWithCanonCtor value = MAPPER.readValue( - a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterMethodWithCanonCtor.class); - - Map expectedAny = new LinkedHashMap<>(); - expectedAny.put("any1", "Any 1"); - expectedAny.put("any2", "Any 2"); - try { - assertEquals(new RecordWorkaroundWithAnySetterMethodWithCanonCtor(123, expectedAny), value); - fail("Used to fail, but is now working again"); - } catch (AssertionFailedError e) { - // Used to work, but stopped working starting from 2.18.0 due to [databind#4558] - verifyException(e, "[id=123, any={}]"); - } - } - - @Test - public void testDeserializeWorkaround_WithAnySetterComponent_WithAltConstructor() throws Exception { - try { - RecordWorkaroundWithAnySetterComponentAltCtor value = MAPPER.readValue( - a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterComponentAltCtor.class); - fail("Used to fail, but is now: " + value); - } catch (UnrecognizedPropertyException e) { - // Used to work, but stopped working starting from 2.15.0 due to [databind#3737] - verifyException(e, "Unrecognized field \"any1\""); - } - } - @Test public void testDeserialize_WithAnySetterComponent_WithCanonicalConstructor() throws Exception { RecordWithAnySetterComponentCanonCtor value = MAPPER.readValue( From 6a54c753875c7b91b6629c41d669844888450498 Mon Sep 17 00:00:00 2001 From: Yih Tsern Date: Mon, 22 Jul 2024 23:00:12 +0800 Subject: [PATCH 3/3] Merge RecordWithJsonAnySetterTest into RecordCreatorWithAnySetter562Test. --- .../RecordCreatorWithAnySetter562Test.java | 62 ++++++++++++++----- .../records/RecordWithJsonAnySetterTest.java | 57 ----------------- 2 files changed, 47 insertions(+), 72 deletions(-) delete mode 100644 src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordCreatorWithAnySetter562Test.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordCreatorWithAnySetter562Test.java index 9fee6af811..5bb2bf4393 100644 --- a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordCreatorWithAnySetter562Test.java +++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordCreatorWithAnySetter562Test.java @@ -7,30 +7,38 @@ import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; import org.junit.jupiter.api.Test; +import java.util.LinkedHashMap; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; // [databind#562] Allow @JsonAnySetter on Creator constructors -public class RecordCreatorWithAnySetter562Test - extends DatabindTestUtil +public class RecordCreatorWithAnySetter562Test extends DatabindTestUtil { - record RecordWithAnySetterCtor(int id, - Map additionalProperties) { + record RecordWithAnySetterCtorParamCanonCtor(int id, Map additionalProperties) { @JsonCreator - public RecordWithAnySetterCtor(@JsonProperty("regular") int id, - @JsonAnySetter Map additionalProperties - ) { + public RecordWithAnySetterCtorParamCanonCtor(@JsonProperty("regular") int id, + @JsonAnySetter Map additionalProperties) { this.id = id; this.additionalProperties = additionalProperties; } } - /* - /********************************************************************** - /* Test methods, alternate constructors - /********************************************************************** - */ + record RecordWithAnySetterComponentCanonCtor(int id, @JsonAnySetter Map any) { + } + + // Workaround mentioned in [databind#3439] + record RecordWorkaroundWithAnySetterMethodWithAltCtor(int id, Map any) { + @JsonCreator + public RecordWorkaroundWithAnySetterMethodWithAltCtor(@JsonProperty("id") int id) { + this(id, new LinkedHashMap<>()); + } + + @JsonAnySetter + private void updateProperty(String name, Object value) { + any.put(name, value); + } + } private final ObjectMapper MAPPER = newJsonMapper(); @@ -38,17 +46,41 @@ public RecordWithAnySetterCtor(@JsonProperty("regular") int id, public void testRecordWithAnySetterCtor() throws Exception { // First, only regular property mapped - RecordWithAnySetterCtor result = MAPPER.readValue(a2q("{'regular':13}"), - RecordWithAnySetterCtor.class); + RecordWithAnySetterCtorParamCanonCtor result = MAPPER.readValue(a2q("{'regular':13}"), + RecordWithAnySetterCtorParamCanonCtor.class); assertEquals(13, result.id); assertEquals(0, result.additionalProperties.size()); // Then with unknown properties result = MAPPER.readValue(a2q("{'regular':13, 'unknown':99, 'extra':-1}"), - RecordWithAnySetterCtor.class); + RecordWithAnySetterCtorParamCanonCtor.class); assertEquals(13, result.id); assertEquals(Integer.valueOf(99), result.additionalProperties.get("unknown")); assertEquals(Integer.valueOf(-1), result.additionalProperties.get("extra")); assertEquals(2, result.additionalProperties.size()); } + + @Test + public void testDeserialize_WithAnySetterComponent_WithCanonicalConstructor() throws Exception + { + RecordWithAnySetterComponentCanonCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWithAnySetterComponentCanonCtor.class); + + Map expectedAny = new LinkedHashMap<>(); + expectedAny.put("any1", "Any 1"); + expectedAny.put("any2", "Any 2"); + assertEquals(new RecordWithAnySetterComponentCanonCtor(123, expectedAny), value); + } + + @Test + public void testDeserializeWorkaround_WithAnySetterMethod_WithAltConstructor() throws Exception + { + RecordWorkaroundWithAnySetterMethodWithAltCtor value = MAPPER.readValue( + a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterMethodWithAltCtor.class); + + Map expectedAny = new LinkedHashMap<>(); + expectedAny.put("any1", "Any 1"); + expectedAny.put("any2", "Any 2"); + assertEquals(new RecordWorkaroundWithAnySetterMethodWithAltCtor(123, expectedAny), value); + } } diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java deleted file mode 100644 index 0996c66c33..0000000000 --- a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordWithJsonAnySetterTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.fasterxml.jackson.databind.records; - -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; -import org.junit.jupiter.api.Test; - -import java.util.LinkedHashMap; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class RecordWithJsonAnySetterTest extends DatabindTestUtil { - - // Workaround mentioned in [databind#3439] - record RecordWorkaroundWithAnySetterMethodWithAltCtor(int id, Map any) { - @JsonCreator - public RecordWorkaroundWithAnySetterMethodWithAltCtor(@JsonProperty("id") int id) { - this(id, new LinkedHashMap<>()); - } - - @JsonAnySetter - private void updateProperty(String name, Object value) { - any.put(name, value); - } - } - - // A proper one without workaround - record RecordWithAnySetterComponentCanonCtor(int id, @JsonAnySetter Map any) { - } - - private final ObjectMapper MAPPER = newJsonMapper(); - - @Test - public void testDeserializeWorkaround_WithAnySetterMethod_WithAltConstructor() throws Exception { - RecordWorkaroundWithAnySetterMethodWithAltCtor value = MAPPER.readValue( - a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWorkaroundWithAnySetterMethodWithAltCtor.class); - - Map expectedAny = new LinkedHashMap<>(); - expectedAny.put("any1", "Any 1"); - expectedAny.put("any2", "Any 2"); - assertEquals(new RecordWorkaroundWithAnySetterMethodWithAltCtor(123, expectedAny), value); - } - - @Test - public void testDeserialize_WithAnySetterComponent_WithCanonicalConstructor() throws Exception { - RecordWithAnySetterComponentCanonCtor value = MAPPER.readValue( - a2q("{'id':123,'any1':'Any 1','any2':'Any 2'}"), RecordWithAnySetterComponentCanonCtor.class); - - Map expectedAny = new LinkedHashMap<>(); - expectedAny.put("any1", "Any 1"); - expectedAny.put("any2", "Any 2"); - assertEquals(new RecordWithAnySetterComponentCanonCtor(123, expectedAny), value); - } -}