From f7cff01d99c0769691d5e033ea36b40ec4ecfbb4 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 10 Dec 2015 13:20:47 +0100 Subject: [PATCH] DATAREST-697 - Fixed unwrapping mode in ProjectionSerializer. Projection serializer now only creates a nested JSON document if it's not in unwrapping mode. Switched to a completely immutable implementation as we were previously mutating state in the request for an unwrapping instance as we were assuming the instances not being reused. --- .../json/PersistentEntityJackson2Module.java | 31 ++++++++++++++----- .../PersistentEntitySerializationTests.java | 19 ++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java index 2832c2502..5f5e4f395 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java @@ -434,19 +434,33 @@ public class PersistentEntityJackson2Module extends SimpleModule { private final LinkCollector collector; private final ResourceMappings mappings; - private boolean unwrapping; + private final boolean unwrapping; /** - * Creates a new {@link ProjectionSerializer} for the given {@link LinkCollector}. + * Creates a new {@link ProjectionSerializer} for the given {@link LinkCollector} and {@link ResourceMappings}. * - * @param collector + * @param collector must not be {@literal null}. + * @param mappings must not be {@literal null}. */ public ProjectionSerializer(LinkCollector collector, ResourceMappings mappings) { + this(collector, mappings, false); + } + + /** + * Creates a new {@link ProjectionSerializer} for the given {@link LinkCollector}, {@link ResourceMappings} whether + * to be in unwrapping mode or not. + * + * @param collector must not be {@literal null}. + * @param mappings must not be {@literal null}. + * @param unwrapping + */ + private ProjectionSerializer(LinkCollector collector, ResourceMappings mappings, boolean unwrapping) { super(TargetAware.class); this.collector = collector; this.mappings = mappings; + this.unwrapping = unwrapping; } /* @@ -461,14 +475,18 @@ public class PersistentEntityJackson2Module extends SimpleModule { Links links = mappings.getMetadataFor(value.getTargetClass()).isExported() ? collector.getLinksFor(target) : new Links(); - jgen.writeStartObject(); + if (!unwrapping) { + jgen.writeStartObject(); + } provider.// findValueSerializer(ProjectionResource.class, null).// unwrappingSerializer(null).// serialize(new ProjectionResource(value, links), jgen, provider); - jgen.writeEndObject(); + if (!unwrapping) { + jgen.writeEndObject(); + } } /* @@ -486,8 +504,7 @@ public class PersistentEntityJackson2Module extends SimpleModule { */ @Override public JsonSerializer unwrappingSerializer(NameTransformer unwrapper) { - this.unwrapping = true; - return this; + return new ProjectionSerializer(collector, mappings, true); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java index f81695bb2..30af2efc3 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java @@ -41,6 +41,7 @@ import org.springframework.data.rest.webmvc.jpa.Order; import org.springframework.data.rest.webmvc.jpa.OrderRepository; import org.springframework.data.rest.webmvc.jpa.Person; import org.springframework.data.rest.webmvc.jpa.PersonRepository; +import org.springframework.data.rest.webmvc.jpa.PersonSummary; import org.springframework.data.rest.webmvc.jpa.UserExcerpt; import org.springframework.data.rest.webmvc.mongodb.Address; import org.springframework.data.rest.webmvc.mongodb.User; @@ -50,6 +51,7 @@ import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkDiscoverer; import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.PagedResources.PageMetadata; +import org.springframework.hateoas.Resource; import org.springframework.hateoas.core.EmbeddedWrapper; import org.springframework.hateoas.core.EmbeddedWrappers; import org.springframework.hateoas.hal.HalLinkDiscoverer; @@ -304,4 +306,21 @@ public class PersistentEntitySerializationTests { public void deserializesTranslatedEnumProperty() throws Exception { assertThat(mapper.readValue("{ \"gender\" : \"Male\" }", User.class).gender, is(Gender.MALE)); } + + /** + * @see DATAREST-697 + */ + @Test + public void rendersProjectionWithinSimpleResourceCorrectly() throws Exception { + + Person person = new Person("Dave", "Matthews"); + person.setId(1L); + + ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); + PersonSummary projection = factory.createProjection(PersonSummary.class, person); + + String result = mapper.writeValueAsString(new Resource(projection)); + + assertThat(JsonPath.read(result, "$._links.self"), is(notNullValue())); + } }