JSON Jackson将不同的密钥解析到同一个字段中

DAr*_*rkO 49 java json jackson

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

public class Media {
 private Asset asset;
}
Run Code Online (Sandbox Code Playgroud)

将json响应解析为此资产POJO时,一切都很完美.但是,这个资产带来的关键点略有不同.它可以是:

  @JsonProperty("cover_asset")
Run Code Online (Sandbox Code Playgroud)

要么

  @JsonProperty("asset")
Run Code Online (Sandbox Code Playgroud)

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

Vik*_*sad 69

好吧,因为只有反序列化才是你关注的问题所以@JsonAlias介绍它2.9是完美的.你可以这样做:

@JsonAlias({"cover_asset", "asset"})
private Asset asset;
Run Code Online (Sandbox Code Playgroud)

@JsonAliasdocs:

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

注意:请确保您更新所有相关的依赖性(annotations,core,databind如果你正在使用它们).annotations没有其他人更新会让我失去运行时错误.

  • 缺省名称是issupported,所以在这种情况下你只需要指定`"cover_asset"`. (3认同)

wha*_*ley 49

更简洁一点,我建议为此使用两个单独的@JsonSetter注释.这是一个有效的例子.这意味着您的java类只有一个getter方法用于属性而不是两个.您还可以使您不希望向Media私有客户端公开的setter以特殊方式处理其中一个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));

    }
}
Run Code Online (Sandbox Code Playgroud)


DRC*_*RCB 7

我建议对两个属性名称使用getter/setter,它们指的是同一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

另请参阅我对可能重复问题的回答: 序列化和反序列化期间JSON属性的不同名称


Rob*_*ide 5

Vikas 和 JsonAlias 的出色回答。

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

@JsonProperty("cover_asset")    
@JsonAlias({"asset", "cover_asset","amazing_asset"})
private Asset asset; 
Run Code Online (Sandbox Code Playgroud)

参考。

  • 效果很好,谢谢!请注意,您不必在别名中重复名称。`@JsonAlias({"asset","amazing_asset"})` 足以涵盖所有三个(`"asset", "cover_asset","amazing_asset"`)。 (2认同)