Skip to content

Instantly share code, notes, and snippets.

@sscovil
Created February 3, 2014 17:31
Show Gist options
  • Save sscovil/8788339 to your computer and use it in GitHub Desktop.
Save sscovil/8788339 to your computer and use it in GitHub Desktop.
This is the correct implementation of @JsonTypeInfo and related annotations when performing polymorphic JSON deserialization on an embedded interface property. It also illustrates the use of an Enum as a type name. See StackOverflow question: http://stackoverflow.com/questions/21485923/java-jackson-polymorphic-json-deserialization-of-an-object-w…
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;
}
}
@ranjithmolgu
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment