Подтвердить что ты не робот

JSON Jackson разбирает разные ключи в одном поле

У меня есть POJO, у которого есть поле:

public class Media {
 private Asset asset;
}

Все работает отлично, анализируя ответ json в этот актив POJO. но, однако, есть небольшая разница с ключом, к которому относится этот актив. Это может быть:

  @JsonProperty("cover_asset")

или

  @JsonProperty("asset")

Есть ли способ аннотировать POJO для распознавания этого случая и де-сериализации в одно и то же поле. Невозможно, чтобы оба они отображались в одном ответе.

4b9b3361

Ответ 1

Более кратко, я бы предложил использовать для этого две отдельные аннотации @JsonSetter. Вот рабочий пример. Это означает, что ваш класс java будет использовать только один метод getter для свойства вместо двух. Вы также можете сделать сеттер, который вы не хотите подвергать контактам со стороны клиентов Media, и обрабатывать один из json-ключей особым образом.

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.ObjectMapper;

@SuppressWarnings("unused")
public class Media {

    private Asset asset;

    @JsonGetter("asset")
    public Asset getAsset() {
        return asset;
    }

    @JsonSetter("asset")
    public void setAsset(Asset asset) {
        this.asset = asset;
    }

    @JsonSetter("cover_asset")
    private void setMediaAsset(Asset asset) {
        if (this.asset == null) {
            setAsset(asset);
        }
    }


    private static class Asset {
        @JsonProperty("foo")
        private String foo;
    }

    public static void main(String[] args) throws Exception {
        String withAsset = "{'asset': {'foo':'bar'}}";
        String withCoverAsset = "{'cover_asset': {'foo':'bar'}}";

        ObjectMapper mapper = new ObjectMapper();
        Media mediaFromAsset = mapper.readValue(withAsset.replace('\'','"'), Media.class);
        Media mediaFromCoverAsset = mapper.readValue(withCoverAsset.replace('\'','"'), Media.class);

        System.out.println(mediaFromAsset.asset.foo.equals(mediaFromCoverAsset.asset.foo));

    }
}

Ответ 2

Я бы предложил использовать getters/setters для обоих имен свойств, которые относятся к одному полю POJO.

public class Media {
    private Asset asset;

    @JsonProperty("cover_asset")
    public Asset getCoverAsset() {
      return asset;
    }

    public void setCoverAsset(Asset asset) {
      this.asset= asset;
    }

    @JsonProperty("asset")
    public Asset getAsset() {
      return asset;
    }

    public void setAsset(Asset asset) {
      this.asset= asset;
    }
}

См. также мой ответ на возможный дублирующий вопрос: Различные имена свойств JSON при сериализации и десериализации

Ответ 3

Хорошо, поскольку ваша проблема связана только с десериализацией, @JsonAlias, представленная в 2.9, идеально подходит для этой ситуации. Вы можете сделать что-то вроде этого:

@JsonAlias({"cover_asset", "asset"})
private Asset asset;

@JsonAlias docs:

Аннотации, которые могут использоваться для определения одного или нескольких альтернативных имен для имущества, принятого во время десериализации в качестве альтернативы Официальное название. Информация о псевдониме также отображается во время POJO интроспекции, но не имеет эффекта во время сериализации, где первичный имя всегда используется.

Примечание. Убедитесь, что вы обновляете все связанные зависимости (annotations, core, databind), если вы их используете. Обновление только annotations без других бросило мне ошибку времени выполнения.