diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPointerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPointerMapping.java index e81cb3bdd..63b58221f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPointerMapping.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/JsonPointerMapping.java @@ -74,7 +74,6 @@ private String verify(String pointer, Class type, BiFunction return pointer; } - PropertyPath base = null; StringBuilder result = new StringBuilder(); TypeInformation currentType = ClassTypeInformation.from(type); @@ -108,13 +107,11 @@ private String verify(String pointer, Class type, BiFunction .orElseThrow(() -> reject(segment, rejectType, pointer, qualifier)); try { - base = base == null ? PropertyPath.from(property, type) : base.nested(segment); + currentType = PropertyPath.from(property, currentType).getTypeInformation(); } catch (PropertyReferenceException o_O) { throw reject(segment, rejectType, pointer, qualifier); } - currentType = base.getTypeInformation(); - result.append("/").append(property); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java index cbddf8cf5..3faf16918 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/patch/SpelPath.java @@ -521,7 +521,7 @@ public SkippedPropertyPath nested(String segment) { return SkippedPropertyPath.of(path.nested(segment), false); } - TypeInformation typeInformation = path.getTypeInformation(); + TypeInformation typeInformation = path.getLeafProperty().getTypeInformation(); return typeInformation.isMap() || typeInformation.isCollectionLike() // ? SkippedPropertyPath.of(path, true) // diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/patch/SpelPathUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/patch/SpelPathUnitTests.java index d4a77ab87..de012b2f9 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/patch/SpelPathUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/patch/SpelPathUnitTests.java @@ -54,6 +54,7 @@ void setUp() { context.getPersistentEntity(MapWrapper.class); context.getPersistentEntity(Todo.class); context.getPersistentEntity(Person.class); + context.getPersistentEntity(Library.class); PersistentEntities entities = new PersistentEntities(Arrays.asList(context)); BindContextFactory factory = new PersistentEntitiesBindContextFactory(entities, @@ -167,6 +168,29 @@ void mapsRenamedProperty() { assertThat(path.getExpressionString()).isEqualTo("renamed"); } + @Test // #2401 + void getsLeafTypeForAppendToCollectionBelowIndexedCollectionElement() { + + WritingOperations path = SpelPath.untyped("/catalog/books/0/reviews/-") // + .bindForWrite(Library.class, context); + + assertThat(path.getExpressionString()).isEqualTo("catalog.books[0].reviews$[true]"); + assertThat(path.getLeafType()).isEqualTo(Review.class); + } + + @Test // #2401 + void appendsToCollectionBelowIndexedCollectionElement() { + + Library library = new Library(); + library.catalog.books.add(new Book()); + + Review review = new Review(); + AddOperation.of("/catalog/books/0/reviews/-", review) // + .perform(library, Library.class, context); + + assertThat(library.catalog.books.get(0).reviews).containsExactly(review); + } + @Test // #2233 void bindsDatesProperly() { @@ -252,4 +276,58 @@ public void setPeopleByInt(Map peopleByInt) { this.peopleByInt = peopleByInt; } } + + // #2401 + + static class Library { + + Catalog catalog = new Catalog(); + + public Catalog getCatalog() { + return this.catalog; + } + + public void setCatalog(Catalog catalog) { + this.catalog = catalog; + } + } + + static class Catalog { + + List books = new ArrayList<>(); + + public List getBooks() { + return this.books; + } + + public void setBooks(List books) { + this.books = books; + } + } + + static class Book { + + List reviews = new ArrayList<>(); + + public List getReviews() { + return this.reviews; + } + + public void setReviews(List reviews) { + this.reviews = reviews; + } + } + + static class Review { + + String text; + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + } }