From db160c4398843f6c9a2b5caeda072b85271e7d71 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 18 Jan 2021 16:04:46 +0100 Subject: [PATCH] GH-1926 - Avoid wrapping nested entities ultimately to represent a value. NestedEntitySerializer now skips the wrapping into an EntityModel if the target serializer is a JsonValueSerializer as EntityModel requires the value to ultimately resolve into key value pairs as it's only enriching something that's rendered as JSON document with hypermedia elements. --- .../json/PersistentEntityJackson2Module.java | 15 ++++++++---- ...rsistentEntityJackson2ModuleUnitTests.java | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 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 0e109f0e9..6a2d098c2 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 @@ -89,6 +89,7 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; +import com.fasterxml.jackson.databind.ser.std.JsonValueSerializer; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; @@ -354,7 +355,7 @@ public class PersistentEntityJackson2Module extends SimpleModule { List resources = new ArrayList(); for (Object element : source) { - resources.add(toModel(element)); + resources.add(toModel(element, provider)); } provider.defaultSerializeValue(resources, gen); @@ -365,13 +366,13 @@ public class PersistentEntityJackson2Module extends SimpleModule { Map resources = CollectionFactory.createApproximateMap(value.getClass(), source.size()); for (Entry entry : source.entrySet()) { - resources.put(entry.getKey(), toModel(entry.getValue())); + resources.put(entry.getKey(), toModel(entry.getValue(), provider)); } provider.defaultSerializeValue(resources, gen); } else { - provider.defaultSerializeValue(toModel(value), gen); + provider.defaultSerializeValue(toModel(value, provider), gen); } } @@ -385,7 +386,13 @@ public class PersistentEntityJackson2Module extends SimpleModule { serialize(value, gen, provider); } - private EntityModel toModel(Object value) { + private Object toModel(Object value, SerializerProvider provider) throws JsonMappingException { + + JsonSerializer serializer = provider.findValueSerializer(value.getClass()); + + if (JsonValueSerializer.class.isInstance(serializer)) { + return value; + } PersistentEntity entity = entities.getRequiredPersistentEntity(value.getClass()); diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java index fb46ba69c..d5d5af6a5 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import lombok.Data; import lombok.Getter; import java.io.IOException; @@ -58,6 +59,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.jayway.jsonpath.JsonPath; @@ -89,6 +91,7 @@ public class PersistentEntityJackson2ModuleUnitTests { mappingContext.getPersistentEntity(SampleWithAdditionalGetters.class); mappingContext.getPersistentEntity(PersistentEntityJackson2ModuleUnitTests.PetOwner.class); mappingContext.getPersistentEntity(Immutable.class); + mappingContext.getPersistentEntity(Wrapper.class); this.persistentEntities = new PersistentEntities(Arrays.asList(mappingContext)); @@ -197,6 +200,16 @@ public class PersistentEntityJackson2ModuleUnitTests { TypeDescriptor.valueOf(Home.class)); } + @Test // GH-1926 + public void doesNotWrapJsonValueTypesIntoEntityModel() throws Exception { + + Wrapper wrapper = new Wrapper(); + wrapper.value = new ValueType(); + wrapper.value.value = "sample"; + + assertThat(mapper.writeValueAsString(wrapper)).isEqualTo("{\"value\":\"sample\"}"); + } + /** * @author Oliver Gierke */ @@ -257,4 +270,15 @@ public class PersistentEntityJackson2ModuleUnitTests { this.home = home; } } + + // GH-1926 + + @Data + static class Wrapper { + ValueType value; + } + + static class ValueType { + @JsonValue String value; + } }