From fc7452bce75b76165ea91dacf5380530a2bf0a94 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Thu, 16 Nov 2023 15:01:03 +0100 Subject: [PATCH] Properly merge non-entity arrays. Fixes #2325. --- .../rest/webmvc/json/DomainObjectReader.java | 8 +-- .../json/DomainObjectReaderUnitTests.java | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java index 0c98c7d2e..ae8462079 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java @@ -267,9 +267,8 @@ public class DomainObjectReader { if (child.isArray()) { - IntFunction rawValues = index -> readRawCollectionElement(property.getComponentType(), fieldName, index, - root, - mapper); + IntFunction rawValues = index -> readRawCollectionElement(property.getComponentType(), fieldName, + index, root, mapper); if (handleArray(child, it, mapper, property.getTypeInformation(), rawValues)) { i.remove(); @@ -366,7 +365,8 @@ public class DomainObjectReader { if (array.isEmpty() || collection.isEmpty() || ClassUtils.isPrimitiveOrWrapper(componentType.getType()) - || componentType.getType().isEnum()) { + || componentType.getType().isEnum() + || entities.getPersistentEntity(componentType.getType()).isEmpty()) { return false; } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java index e4c27a76d..12dca940b 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java @@ -114,6 +114,7 @@ class DomainObjectReaderUnitTests { mappingContext.getPersistentEntity(Pear.class); mappingContext.getPersistentEntity(WithCustomMappedPrimitiveCollection.class); mappingContext.getPersistentEntity(BugModel.class); + mappingContext.getPersistentEntity(ArrayListHolder.class); mappingContext.afterPropertiesSet(); this.entities = new PersistentEntities(Collections.singleton(mappingContext)); @@ -705,6 +706,42 @@ class DomainObjectReaderUnitTests { .containsExactly("Foo", "Bar"); } + @Test // #2325 + void arraysCanMutateAndAppendDuringMerge() throws Exception { + + ObjectMapper mapper = new ObjectMapper(); + ArrayHolder target = new ArrayHolder(new String[] { "ancient", "old", "older" }); + JsonNode node = mapper.readTree("{ \"array\" : [ \"new\", \"old\", \"newer\", \"bleeding edge\" ] }"); + + ArrayHolder updated = reader.doMerge((ObjectNode) node, target, mapper); + + assertThat(updated.array).containsExactly("new", "old", "newer", "bleeding edge"); + } + + @Test // #2325 + void arraysCanAppendMoreThanOneElementDuringMerge() throws Exception { + + ObjectMapper mapper = new ObjectMapper(); + ArrayListHolder target = new ArrayListHolder("ancient", "old", "older"); + JsonNode node = mapper.readTree("{ \"values\" : [ \"ancient\", \"old\", \"older\", \"new\", \"newer\" ] }"); + + ArrayListHolder updated = reader.doMerge((ObjectNode) node, target, mapper); + + assertThat(updated.values).containsExactly("ancient", "old", "older", "new", "newer"); + } + + @Test // #2325 + void arraysCanRemoveElementsDuringMerge() throws Exception { + + ObjectMapper mapper = new ObjectMapper(); + ArrayHolder target = new ArrayHolder(new String[] { "ancient", "old", "older" }); + JsonNode node = mapper.readTree("{ \"array\" : [ \"ancient\" ] }"); + + ArrayHolder updated = reader.doMerge((ObjectNode) node, target, mapper); + + assertThat(updated.array).containsExactly("ancient"); + } + @SuppressWarnings("unchecked") private static T as(Object source, Class type) { @@ -997,4 +1034,16 @@ class DomainObjectReaderUnitTests { public String value; } } + + static class ArrayListHolder { + Collection values; + + ArrayListHolder(String... values) { + this.values = new ArrayList<>(Arrays.asList(values)); + } + + public void setValues(Collection values) { + this.values = values; + } + } }