Использование полиморфизма во время десериализации с Джексоном (и MrBean) - PullRequest
2 голосов
/ 03 марта 2012

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

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

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

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

Я также следовал инструкциям в другом сообщении StackOverflow , и я получаю ту же ошибку.

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

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

Спасибо!

Ответы [ 2 ]

0 голосов
/ 27 марта 2014

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

При использовании @JsonTypeInfo сохранение имени класса довольно просто, но Джексон позволяет вам настроить его по своему вкусу.

Например, предположим, что служба генерирует 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 во время выполнения при десериализации, а также автоматически сгенерировать свойство видов в зависимости от типа среды выполнения. Надеюсь, это поможет!

0 голосов
/ 03 марта 2012

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

...