简体   繁体   中英

Java: Jackson polymorphic JSON deserialization of an object with an interface property?

I am using Jackson's ObjectMapper to deserialize a JSON representation of an object that contains an interface as one of its properties. A simplified version of the code can be seen here:

https://gist.github.com/sscovil/8735923

Basically, I have a class Asset with two properties: type and properties . The JSON model looks like this:

{
    "type": "document",
    "properties": {
        "source": "foo",
        "proxy": "bar"
    }
}

The properties property is defined as an interface called AssetProperties , and I have several classes that implement it (eg DocumentAssetProperties , ImageAssetProperties ). The idea is that image files have different properties (height, width) than document files, etc.

I've worked off of the examples in this article , read through docs and questions here on SO and beyond, and experimented with different configurations in the @JsonTypeInfo annotation parameters, but haven't been able to crack this nut. Any help would be greatly appreciated.

Most recently, the exception I'm getting is this:

java.lang.AssertionError: Could not deserialize JSON.
...
Caused by: org.codehaus.jackson.map.JsonMappingException: Could not resolve type id 'source' into a subtype of [simple type, class AssetProperties]

Thanks in advance!

SOLUTION:

With many thanks to @Michał Ziober, I was able to resolve this issue. I was also able to use an Enum as a type id, which took a bit of Googling. Here is an updated Gist with working code:

https://gist.github.com/sscovil/8788339

You should use JsonTypeInfo.As.EXTERNAL_PROPERTY instead of JsonTypeInfo.As.PROPERTY . In this scenario your Asset class should look like this:

class Asset {

    @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 AssetProperties getProperties() {
        return properties;
    }

    public void setProperties(AssetProperties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "Asset [properties("+properties.getClass().getSimpleName()+")=" + properties + "]";
    }
}

See also my answer in this question: Jackson JsonTypeInfo.As.EXTERNAL_PROPERTY doesn't work as expected .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM