diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index a421560c6f..6560f0767a 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -1544,6 +1544,10 @@ Gili Tzabari (cowwoc@github) * Reported #3063: `@JsonValue` fails for Java Record (2.14.2) +Yury Molchan (yurkom@github) + * Contributed #4121: Preserve the original component type in merging to an array + (2.14.4) + Joo Hyuk Kim (JooHyukKim@github) * Contributed #2536: Add `EnumFeature.READ_ENUM_KEYS_USING_INDEX` to work with existing "WRITE_ENUM_KEYS_USING_INDEX" @@ -1638,5 +1642,3 @@ Antti Lampinen (arlampin@github) * Reported #3897: 2.15.0 breaks deserialization when POJO/Record only has a single field and is marked `Access.WRITE_ONLY` (2.15.1) - - diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index d4ea245e5c..e86ef804b8 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -8,6 +8,8 @@ Project: jackson-databind #3968: Records with additional constructors failed to deserialize (fix contributed by Sim Y-T) +#4121: Preserve the original component type in merging to an array + (contributed by Yury M) 2.15.2 (30-May-2023) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java index 904f8bc0a7..f92b46effd 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.lang.reflect.Array; +import java.util.Arrays; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonFormat; @@ -258,8 +259,7 @@ public Object[] deserialize(JsonParser p, DeserializationContext ctxt, return intoValue; } final int offset = intoValue.length; - Object[] result = new Object[offset + arr.length]; - System.arraycopy(intoValue, 0, result, 0, offset); + Object[] result = Arrays.copyOf(intoValue, offset + arr.length); System.arraycopy(arr, 0, result, offset, arr.length); return result; } diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java index ede4212122..1a4d47e095 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java @@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.*; +import java.util.Date; + public class ArrayMergeTest extends BaseMapTest { static class MergedX @@ -20,6 +22,13 @@ static class MergedX protected MergedX() { } } + // [databind#4121] + static class Merged4121 + { + @JsonMerge(OptBoolean.TRUE) + public Date[] value; + } + /* /******************************************************** /* Test methods @@ -57,6 +66,31 @@ public void testObjectArrayMerging() throws Exception assertEquals("zap", result.value[2]); } + // [databind#4121] + public void testComponentTypeArrayMerging() throws Exception + { + Merged4121 input = new Merged4121(); + input.value = new Date[] {new Date(1000L)}; + Merged4121 result = MAPPER.readerFor(Merged4121.class) + .withValueToUpdate(input) + .readValue(a2q("{'value':[2000]}")); + assertSame(input, result); + assertEquals(2, result.value.length); + assertEquals(1000L, result.value[0].getTime()); + assertEquals(2000L, result.value[1].getTime()); + + // and with one trick + result = MAPPER.readerFor(Merged4121.class) + .with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .withValueToUpdate(input) + .readValue(a2q("{'value':3000}")); + assertSame(input, result); + assertEquals(3, result.value.length); + assertEquals(1000L, result.value[0].getTime()); + assertEquals(2000L, result.value[1].getTime()); + assertEquals(3000L, result.value[2].getTime()); + } + public void testStringArrayMerging() throws Exception { MergedX input = new MergedX(new String[] { "foo" });