#1157 - Register custom serializers to handle Map based EntityModel instances.
We now register a custom serializer to massage EntityModel instances into dedicated types that – in case of a Map being the content of the entity model – wrap the model into a type that applies the necessary Jackson tweaks to properly unwrap a Map.
This commit is contained in:
@@ -45,12 +45,14 @@ import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonStreamContext;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
@@ -69,6 +71,7 @@ import com.fasterxml.jackson.databind.ser.ContainerSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.MapSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
|
||||
/**
|
||||
@@ -91,6 +94,8 @@ public class Jackson2HalModule extends SimpleModule {
|
||||
setMixInAnnotation(Link.class, LinkMixin.class);
|
||||
setMixInAnnotation(RepresentationModel.class, RepresentationModelMixin.class);
|
||||
setMixInAnnotation(CollectionModel.class, CollectionModelMixin.class);
|
||||
|
||||
addSerializer(EntityModel.class, new EntityModelSerializer());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,6 +110,75 @@ public class Jackson2HalModule extends SimpleModule {
|
||||
return LinkMixin.class.equals(mapper.findMixInClassFor(Link.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom serializer for {@link EntityModel} to make sure we get {@link Map} instances properly unwrapped. The
|
||||
* serializer wraps the model instance into a dedicated classes that apply the proper Jackson configuration that's
|
||||
* needed to achieve this and serializes those.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @see https://github.com/FasterXML/jackson-databind/issues/171
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
static class EntityModelSerializer extends StdSerializer<EntityModel> {
|
||||
|
||||
private static final long serialVersionUID = -5933309398043585183L;
|
||||
|
||||
public EntityModelSerializer() {
|
||||
super(EntityModel.class, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* (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
|
||||
@SuppressWarnings("null")
|
||||
public void serialize(EntityModel value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||
|
||||
Object content = value.getContent();
|
||||
|
||||
RepresentationModel<?> wrapped = Map.class.isInstance(content) //
|
||||
? new MapModel(value) //
|
||||
: new NonMapModel(value);
|
||||
|
||||
provider.defaultSerializeValue(wrapped, gen);
|
||||
}
|
||||
|
||||
static class MapModel extends RepresentationModel<MapModel> {
|
||||
|
||||
private final @Nullable Map<?, ?> map;
|
||||
|
||||
public MapModel(EntityModel<?> model) {
|
||||
|
||||
super(model.getLinks().toList());
|
||||
|
||||
this.map = (Map<?, ?>) model.getContent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@JsonAnyGetter
|
||||
public Map<?, ?> getContent() {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
static class NonMapModel extends RepresentationModel<NonMapModel> {
|
||||
|
||||
private final EntityModel<?> model;
|
||||
|
||||
public NonMapModel(EntityModel<?> model) {
|
||||
super(model.getLinks().toList());
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@JsonUnwrapped
|
||||
public Object getContent() {
|
||||
return model.getContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link JsonSerializer} to render Link instances in HAL compatible JSON.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user