2012-03-02 2 views
2

Я использую Jackson для десериализации некоторых JSON в Java POJO. Я регистрирую модуль MrBean с помощью моего объекта mapper, поэтому все, что мне нужно сделать, это определить связку интерфейсов, а POJO создаются автоматически, основываясь на этих интерфейсах.Использование полиморфизма при времени десериализации с помощью Jackson (и MrBean)

Я хотел был бы иметь интерфейс учетных данных с различными типами учетных данных, которые расширяют его, например. UsernamePasswordCredentials и CertificateFileCredentials.

Делать это без каких-либо аннотаций или других заклинаниями, чтобы попытаться сделать это работа дает мне следующую ошибку в моем тестовом модуле:

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "username" (Class org.codehaus.jackson.generated.SCRUBBED.Credentials), not marked as ignorable 
at [Source: [email protected]; line: 32, column: 29] (through reference chain: HostConfiguration["hostDefinitions"]->HostDefinition["credentials"]->Credentials["username"]) 

Я также followed the instructions at another StackOverflow post, и я получаю ту же ошибку.

Ошибка имеет смысл; Джексон пытается сопоставить содержимое моего файла JSON с пустым интерфейсом. Тем не менее, я (наивно, возможно) ожидал, что Джексон будет искать интерфейсы, расширяющие базовый интерфейс Credentials и пытающиеся сопоставить поля в этих интерфейсах с полями, найденными в объекте JSON.

Я видел несколько примеров на вики Джексона, которые используют метаинформацию в объекте JSON, например. украшая объект "@class":"foo.bar.CertificateFileCredentials", но я бы предпочел избежать этого, так как мой вход JSON будет генерироваться автоматически другими службами, а эти другие службы не должны знать ничего о внутренних функциях моего сервиса.

Спасибо!

ответ

0

Как вы определяете фактические классы реализации? Как дополнительные интерфейсы? Они должны генерироваться правильно; но проблема заключается во время десериализации: для десериализатора должен быть какой-то способ найти фактический тип для использования, если есть несколько вариантов. Для этого рекомендуется использовать @JsonTypeInfo, как вы заметили.

0

На самом деле, техника будет хорошо работать и для ваших целей, даже если вы не контролируете службу, которая генерирует JSON.

Сохранение имени класса является хорошим простым по умолчанию при использовании @JsonTypeInfo, но Jackson позволяет настроить его по своему вкусу.

Например, предположим, что служба генерирует JSON, который выглядит следующим образом:

{ meows: 400, furColor: "green", species: "cat" } 

Затем вы можете определить эти интерфейсы, чтобы преобразовать его правильно.

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY,property="species") 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value=Feline.class, name="cat") 
}) 
public interface Animal { 
    public String getFurColor(); 
} 

@JsonTypeName("cat") 
public interface Feline extends Animal { 
    @JsonProperty("meows") // just to have an example of a renamed property... 
    public long getMeowingVolumeInDecibels(); 
} 

Тогда вы просто должны автоматически получить правильный тип Java во время выполнения при десериализации, а также автоматически генерировать свойство «вида» в зависимости от типа исполнения. Надеюсь, это поможет!

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