2014-01-31 4 views
15

Я использую Jackson's ObjectMapper для десериализации представления JSON объекта, который содержит интерфейс как один из его свойств. Упрощенная версия кода можно увидеть здесь:Java: Джексон полиморфная JSON десериализация объекта с свойством интерфейса?

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

В принципе, у меня есть класс Asset с двумя свойствами: type и properties. Модель JSON выглядит следующим образом:

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

Свойство properties определяется как интерфейс называется AssetProperties, и у меня есть несколько классов, которые реализуют его (например DocumentAssetProperties, ImageAssetProperties). Идея состоит в том, что файлы изображений имеют разные свойства (высота, ширина), чем файлы документов, и т. Д.

Я работал с примерами в this article, прочитал документы и вопросы здесь, на SO и за его пределами, и экспериментировал с разными конфигурации в параметрах аннотации @JsonTypeInfo, но они не смогли взломать эту гайку. Любая помощь будет принята с благодарностью.

Совсем недавно, исключение я получаю это:

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] 

Заранее спасибо!

РЕШЕНИЕ:

С большое спасибо @ Михал Ziober, я был в состоянии решить эту проблему. Я также мог использовать Enum в качестве идентификатора типа, который занимал часть Googling. Вот обновленный Gist с рабочим кодом:

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

+0

Что делает вывод Json для чего-то подобного? Есть ли множество встроенных метаданных? – ingyhere

+0

Спасибо за ссылку на сообщение programmerbruce. Какой замечательный ресурс – slugmandrew

ответ

15

Вы должны использовать JsonTypeInfo.As.EXTERNAL_PROPERTY вместо JsonTypeInfo.As.PROPERTY. В этом случае ваш Asset класс должен выглядеть следующим образом:

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 + "]"; 
    } 
} 

Смотрите также мой ответ на этот вопрос: Jackson JsonTypeInfo.As.EXTERNAL_PROPERTY doesn't work as expected.

+1

Добавьте аннотации к собственности, а не к классу ... конечно! Блестяще, спасибо! –

+0

Теперь сделайте это для списка интерфейсов, пожалуйста. ... :) – ingyhere

+0

Как выглядят ваши 'POJO' и 'JSON'? –

Смежные вопросы