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.
This commit is contained in:
Oliver Drotbohm
2021-01-18 16:04:46 +01:00
parent 96a6e47dfe
commit db160c4398
2 changed files with 35 additions and 4 deletions

View File

@@ -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<Object> resources = new ArrayList<Object>();
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<Object, Object> 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<Object> toModel(Object value) {
private Object toModel(Object value, SerializerProvider provider) throws JsonMappingException {
JsonSerializer<Object> serializer = provider.findValueSerializer(value.getClass());
if (JsonValueSerializer.class.isInstance(serializer)) {
return value;
}
PersistentEntity<?, ?> entity = entities.getRequiredPersistentEntity(value.getClass());

View File

@@ -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;
}
}