#1157 - Fixed custom EntityModel serialization for Map payloads.
Using a custom serializer seems to break downstream projects that also register serializers for EntityModel. We're now using extra methods on EntityModel itself that do the trick as well.
This commit is contained in:
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
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;
|
||||
|
||||
@@ -80,6 +81,11 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
|
||||
|
||||
// Hacks to allow deserialization into an EntityModel<Map<String, Object>>
|
||||
|
||||
@JsonAnyGetter
|
||||
private Map<String, Object> getMapContent() {
|
||||
return Map.class.isInstance(content) ? (Map<String, Object>) content : null;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
private void setPropertiesAsMap(String key, Object value) {
|
||||
getOrInitAsMap().put(key, value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,7 +45,6 @@ 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;
|
||||
@@ -70,7 +69,6 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -93,8 +91,6 @@ 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());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,75 +105,6 @@ 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