-
-
Save sscovil/8788339 to your computer and use it in GitHub Desktop.
| public class Asset { | |
| private AssetType type; | |
| @JsonTypeInfo( | |
| use = JsonTypeInfo.Id.NAME, | |
| include = JsonTypeInfo.As.EXTERNAL_PROPERTY, | |
| property = "type" | |
| ) | |
| @JsonSubTypes({ | |
| @JsonSubTypes.Type(value = ImageAssetProperties.class, name = "image"), | |
| @JsonSubTypes.Type(value = DocumentAssetProperties.class, name = "document") | |
| }) | |
| private AssetProperties properties; | |
| public String getType() { | |
| return type.toString(); | |
| } | |
| @JsonProperty("type") | |
| public void setType(String type) { | |
| this.type = AssetType.fromString(type); | |
| } | |
| @JsonIgnore | |
| public void setType(AssetType type) { | |
| this.type = type; | |
| } | |
| public AssetProperties getProperties() { | |
| return properties; | |
| } | |
| public void setProperties(AssetProperties properties) { | |
| this.properties = properties; | |
| } | |
| } |
| public interface AssetProperties { | |
| String getSource(); | |
| AssetProperties setSource(String source); | |
| String getProxy(); | |
| AssetProperties setProxy(String proxy); | |
| } |
| public enum AssetType { | |
| IMAGE("image"), | |
| DOCUMENT("document"); | |
| private String string; | |
| AssetType(String string) { | |
| this.string = string; | |
| } | |
| public static AssetType fromString(String string) { | |
| // Enum.valueOf() method is case sensitive; this method is not. | |
| if (string != null) | |
| for (AssetType assetType : AssetType.values()) | |
| if (string.equalsIgnoreCase(assetType.toString())) | |
| return assetType; | |
| throw new IllegalArgumentException(String.format("%s is not a valid AssetType.", string); | |
| } | |
| public String toString() { | |
| return this.string; | |
| } | |
| } |
| public class DocumentAssetProperties implements AssetProperties { | |
| private String source; | |
| private String proxy; | |
| public String getSource() { | |
| return source; | |
| } | |
| public DocumentAssetProperties setSource(String source) { | |
| this.source = source; | |
| return this; | |
| } | |
| public String getProxy() { | |
| return proxy; | |
| } | |
| public DocumentAssetProperties setProxy(String proxy) { | |
| this.proxy = proxy; | |
| return this; | |
| } | |
| } |
| public class ImageAssetProperties implements AssetProperties { | |
| private String source; | |
| private String proxy; | |
| private Integer height; | |
| private Integer width; | |
| public String getSource() { | |
| return source; | |
| } | |
| public ImageAssetProperties setSource(String source) { | |
| this.source = source; | |
| return this; | |
| } | |
| public String getProxy() { | |
| return proxy; | |
| } | |
| public ImageAssetProperties setProxy(String proxy) { | |
| this.proxy = proxy; | |
| return this; | |
| } | |
| public Integer getHeight() { | |
| return height; | |
| } | |
| public ImageAssetProperties setHeight(Integer height) { | |
| this.height = height; | |
| return this; | |
| } | |
| public Integer getWidth() { | |
| return width; | |
| } | |
| public ImageAssetProperties setWidth(Integer width) { | |
| this.width = width; | |
| return this; | |
| } | |
| } |
| public class PolymorphicDeserializationTests { | |
| @Test | |
| public void deserializeJsonSucceeds() { | |
| Asset asset = deserializeJson("{ \"type\": \"document\", \"properties\": { \"source\": \"foo\", \"proxy\": \"bar\" } }"); | |
| Assert.assertTrue(asset.getProperties() instanceof DocumentAssetProperties); | |
| } | |
| public Asset deserializeJson(String json) { | |
| ObjectMapper mapper = new ObjectMapper(); | |
| try { | |
| return mapper.readValue(json, Asset.class); | |
| } | |
| catch(IOException e) { | |
| Assert.fail("Could not deserialize JSON.", e); | |
| } | |
| return null; | |
| } | |
| } |
I also had some difficulty getting this to work. I was receiving the following exception
com.fasterxml.jackson.databind.JsonMappingException: Missing property 'content'
for external type id 'contentTypeI ended up having to add the @JsonTypeId annotation to the type field referenced as the EXTERNAL_PROPERTY
public interface Content {
}
public class Post implements Content {
public String content = "bar";
}
public class Foo {
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "contentType")
@JsonSubTypes({
@JsonSubTypes.Type(value = Post.class, name = "post")
})
public Content content;
@JsonTypeId
public ContentType contentType;
public enum ContentType {
"post"
}
}I believe this Stack Exchange question is a similar issue.
Any idea how you'd do this without using an external property?
I've got a setup that looks like this:
1st request
{
"foo": "bar",
"a": {
"spam": "lots of spam",
}
}2nd request
{
"foo": "bar",
"b": {
"eggs": "lots of eggs",
}
}public interface AB { }
@JsonTypeName("b")
public class A implements AB {
@JsonProperty("spam")
public String spam:
}
@JsonTypeName("b")
public class B implements AB {
@JsonProperty("eggs")
public String eggs;
}
public class Container {
@JsonProperty("foo")
public String foo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({@JsonSubTypes.Type(value = A.class), @JsonSubTypes.Type(value = B.class)})
public AB ab;
}However my tests trying to deserialize a container end with Unrecognized field "a", not marked as ignorable (2 known properties: "foo", "ab") ... :\
I'm trying serialize java object to JSON by skipping the interface class name in the serialized string. Is there a way we can do it?
The details are at: https://stackoverflow.com/questions/45270140/how-to-serialize-java-to-json-without-including-the-interface-name-in-the-serial
I've tried to use this approach and unfortunately this does not work for me. So now instead of having 1 instance there are two. One precedes the object and after that follows it. When I'm trying to de-serialize the first object causes a problem like:
"Missing property 'name' for external type id"