#1352 - Change in implementation strategy for Maps in EntityModel.
We now use a custom serializer for EntityModel.getContent() as we need that to still return the Map content for programmatic clients. The serializer skips maps entirely and programmatically unwraps all other content. A simple Converter (@JsonSerialize(convert = …)) to filter Maps unfortunately didn't do the trick as that causes a a delegating serializer to be registered for the property and @JsonUnwrapped stops working as it's designed to work with bean serializers only. Adapted test cases accordingly. Original pull request: #1353.
This commit is contained in:
@@ -15,20 +15,24 @@
|
||||
*/
|
||||
package org.springframework.hateoas;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.fasterxml.jackson.databind.util.NameTransformer;
|
||||
|
||||
/**
|
||||
* A simple {@link EntityModel} wrapping a domain object and adding links to it.
|
||||
@@ -116,10 +120,11 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
|
||||
*
|
||||
* @return the content
|
||||
*/
|
||||
@JsonUnwrapped
|
||||
@Nullable
|
||||
@JsonUnwrapped
|
||||
@JsonSerialize(using = MapSuppressingUnwrappingSerializer.class)
|
||||
public T getContent() {
|
||||
return !Map.class.isInstance(content) ? content : null;
|
||||
return content;
|
||||
}
|
||||
|
||||
// Hacks to allow deserialization into an EntityModel<Map<String, Object>>
|
||||
@@ -127,7 +132,7 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
|
||||
@Nullable
|
||||
@JsonAnyGetter
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getMapContent() {
|
||||
private Map<String, Object> getMapContent() {
|
||||
return Map.class.isInstance(content) ? (Map<String, Object>) content : null;
|
||||
}
|
||||
|
||||
@@ -189,4 +194,36 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
|
||||
result += content == null ? 0 : 17 * content.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class MapSuppressingUnwrappingSerializer extends StdSerializer<Object> {
|
||||
|
||||
public MapSuppressingUnwrappingSerializer() {
|
||||
super(Object.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.ser.std.StdSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider)
|
||||
*/
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||
|
||||
if (value == null || Map.class.isInstance(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
provider.findValueSerializer(value.getClass()) //
|
||||
.unwrappingSerializer(NameTransformer.NOP) //
|
||||
.serialize(value, gen, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.fasterxml.jackson.databind.JsonSerializer#isUnwrappingSerializer()
|
||||
*/
|
||||
@Override
|
||||
public boolean isUnwrappingSerializer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user