71

我有一个 POJO,它有一个字段:

public class Media {
 private Asset asset;
}

将 json 响应解析为此资产 POJO 时,一切正常。但是,该资产附带的密钥略有不同。它可以是:

  @JsonProperty("cover_asset")

或者

  @JsonProperty("asset")

有没有办法注释 POJO 以识别这种情况并反序列化到同一字段中。他们不可能出现在同一个响应中。

4

4 回答 4

112

好吧,由于您只关心反序列化,因此@JsonAlias引入 in2.9非常适合这种情况。你可以这样做:

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

@JsonAlias文档

可用于为属性定义一个或多个替代名称的注释,在反序列化过程中被接受为官方名称的替代名称。别名信息也在 POJO 内省期间公开,但在始终使用主名称的序列化期间无效。

注意:如果您正在使用它们,请确保更新所有相关的依赖项(、、、annotations) 。在没有其他人的情况下更新给我带来了运行时错误。coredatabindannotations

于 2017-12-01T10:51:23.433 回答
50

更简洁地说,我建议为此使用两个单独的 @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));

    }
}
于 2013-10-24T12:35:48.103 回答
8

我建议对引用相同 POJO 字段的两个属性名称使用 getter/setter。

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 属性的不同名称

于 2013-10-24T11:50:55.470 回答
6

Vikas 与 JsonAlias 的出色回答。

只是补充一点,您还可以从这两个世界中受益(JsonProperty&Alias)[自杰克逊 2.9 以来]:

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

参考。

于 2019-11-04T13:33:06.510 回答