Skip to content

Commit d6f0f3a

Browse files
committed
Properly merge non-entity arrays.
Fixes #2325.
1 parent 2b207b1 commit d6f0f3a

File tree

2 files changed

+67
-10
lines changed

2 files changed

+67
-10
lines changed

spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/DomainObjectReader.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,8 @@ <T> T doMerge(ObjectNode root, T target, ObjectMapper mapper) throws Exception {
267267

268268
if (child.isArray()) {
269269

270-
IntFunction<Object> rawValues = index -> readRawCollectionElement(property.getComponentType(), fieldName, index,
271-
root,
272-
mapper);
270+
IntFunction<Object> rawValues = index -> readRawCollectionElement(property.getComponentType(), fieldName,
271+
index, root, mapper);
273272

274273
if (handleArray(child, it, mapper, property.getTypeInformation(), rawValues)) {
275274
i.remove();
@@ -366,7 +365,8 @@ private boolean handleArrayNode(ArrayNode array, Collection<Object> collection,
366365
if (array.isEmpty()
367366
|| collection.isEmpty()
368367
|| ClassUtils.isPrimitiveOrWrapper(componentType.getType())
369-
|| componentType.getType().isEnum()) {
368+
|| componentType.getType().isEnum()
369+
|| entities.getPersistentEntity(componentType.getType()).isEmpty()) {
370370
return false;
371371
}
372372

spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/DomainObjectReaderUnitTests.java

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void setUp() {
108108
mappingContext.getPersistentEntity(Pear.class);
109109
mappingContext.getPersistentEntity(WithCustomMappedPrimitiveCollection.class);
110110
mappingContext.getPersistentEntity(BugModel.class);
111+
mappingContext.getPersistentEntity(ArrayListHolder.class);
111112
mappingContext.afterPropertiesSet();
112113

113114
this.entities = new PersistentEntities(Collections.singleton(mappingContext));
@@ -699,6 +700,42 @@ void deserializesNewNestedEntitiesCorrectly() throws Exception {
699700
.containsExactly("Foo", "Bar");
700701
}
701702

703+
@Test // #2325
704+
void arraysCanMutateAndAppendDuringMerge() throws Exception {
705+
706+
ObjectMapper mapper = new ObjectMapper();
707+
ArrayHolder target = new ArrayHolder(new String[] { "ancient", "old", "older" });
708+
JsonNode node = mapper.readTree("{ \"array\" : [ \"new\", \"old\", \"newer\", \"bleeding edge\" ] }");
709+
710+
ArrayHolder updated = reader.doMerge((ObjectNode) node, target, mapper);
711+
712+
assertThat(updated.array).containsExactly("new", "old", "newer", "bleeding edge");
713+
}
714+
715+
@Test // #2325
716+
void arraysCanAppendMoreThanOneElementDuringMerge() throws Exception {
717+
718+
ObjectMapper mapper = new ObjectMapper();
719+
ArrayListHolder target = new ArrayListHolder("ancient", "old", "older");
720+
JsonNode node = mapper.readTree("{ \"values\" : [ \"ancient\", \"old\", \"older\", \"new\", \"newer\" ] }");
721+
722+
ArrayListHolder updated = reader.doMerge((ObjectNode) node, target, mapper);
723+
724+
assertThat(updated.values).containsExactly("ancient", "old", "older", "new", "newer");
725+
}
726+
727+
@Test // #2325
728+
void arraysCanRemoveElementsDuringMerge() throws Exception {
729+
730+
ObjectMapper mapper = new ObjectMapper();
731+
ArrayHolder target = new ArrayHolder(new String[] { "ancient", "old", "older" });
732+
JsonNode node = mapper.readTree("{ \"array\" : [ \"ancient\" ] }");
733+
734+
ArrayHolder updated = reader.doMerge((ObjectNode) node, target, mapper);
735+
736+
assertThat(updated.array).containsExactly("ancient");
737+
}
738+
702739
@SuppressWarnings("unchecked")
703740
private static <T> T as(Object source, Class<T> type) {
704741

@@ -837,25 +874,31 @@ public LocalizedValue(String value) {
837874

838875
public LocalizedValue() {}
839876

877+
@Override
840878
public boolean equals(final Object o) {
841-
if (o == this)
879+
if (o == this) {
842880
return true;
843-
if (!(o instanceof LocalizedValue))
881+
}
882+
if (!(o instanceof LocalizedValue)) {
844883
return false;
884+
}
845885
final LocalizedValue other = (LocalizedValue) o;
846-
if (!other.canEqual((Object) this))
886+
if (!other.canEqual(this)) {
847887
return false;
888+
}
848889
final Object this$value = this.value;
849890
final Object other$value = other.value;
850-
if (this$value == null ? other$value != null : !this$value.equals(other$value))
891+
if (this$value == null ? other$value != null : !this$value.equals(other$value)) {
851892
return false;
893+
}
852894
return true;
853895
}
854896

855897
protected boolean canEqual(final Object other) {
856898
return other instanceof LocalizedValue;
857899
}
858900

901+
@Override
859902
public int hashCode() {
860903
final int PRIME = 59;
861904
int result = 1;
@@ -918,10 +961,12 @@ public List<Nested> getNested() {
918961

919962
@Override
920963
public boolean equals(Object o) {
921-
if (this == o)
964+
if (this == o) {
922965
return true;
923-
if (o == null || getClass() != o.getClass())
966+
}
967+
if (o == null || getClass() != o.getClass()) {
924968
return false;
969+
}
925970

926971
SampleWithReference that = (SampleWithReference) o;
927972

@@ -1071,4 +1116,16 @@ static class NestedModel {
10711116
public String value;
10721117
}
10731118
}
1119+
1120+
static class ArrayListHolder {
1121+
Collection<String> values;
1122+
1123+
ArrayListHolder(String... values) {
1124+
this.values = new ArrayList<>(Arrays.asList(values));
1125+
}
1126+
1127+
public void setValues(Collection<String> values) {
1128+
this.values = values;
1129+
}
1130+
}
10741131
}

0 commit comments

Comments
 (0)