@JsonUnwrapped的Jackson反序列化等效是什么?

62

假设我有以下的类:

public class Parent {
  public int age;
  @JsonUnwrapped
  public Name name;
}

生成JSON:

{
  "age" : 18,
  "first" : "Joey",
  "last" : "Sixpack"
}

我该如何将其反序列化回父类?我可以使用@JsonCreator

@JsonCreator
public Parent(Map<String,String> jsonMap) {
  age = jsonMap.get("age");
  name = new Name(jsonMap.get("first"), jsonMap.get("last"));
}

但这也会有效地将@JsonIgnoreProperties(ignoreUnknown=true)添加到父类中,因为所有属性都映射到此处。因此,如果您希望未知的JSON字段引发异常,您需要自己处理。另外,如果映射值可能是字符串以外的其他东西,您需要进行一些手动类型检查和转换。Jackson是否有自动处理此情况的方法?

编辑:我可能有点疯了,但事实证明这实际上可以工作,尽管在文档中从未明确提到:http://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
我相当确定它之前对我不起作用。然而,当需要自定义逻辑来反序列化展开的多态类型时,建议使用提议的@JsonCreator方法。


6
您确定 @JsonUnwrapped 在反序列化时有效吗?我刚刚尝试了一下,当我尝试反序列化扁平化的JSON时,出现了 无法读取JSON:未知字段... 的错误。 - E-Riz
5个回答

39
您可以为每个字段使用@JsonCreator@JsonProperty一起使用:

@JsonCreator
public Parent(@JsonProperty("age") Integer age, @JsonProperty("firstName") String firstName,
        @JsonProperty("lastName") String lastName) {
    this.age = age;
    this.name = new Name(firstName, lastName);
}

Jackson在这种情况下会为您执行类型检查和未知字段检查。


2
好观点。这确实回答了如何在一般的JsonCreators中保留jackson类型/字段检查的问题,这可能是唯一有用的问题了。=) - Shaun

17

5

@JsonUnwrapped 在序列化和反序列化时均可使用,您不需要采取任何额外的步骤。


4
使用@JsonUnwrapped在将JSON反序列化回Parent类时,不需要对源对象进行任何更改。
尽管在Jackson 2.13之前的Javadocs中没有提到(参见 jackson-annotations#184),但@JsonUnwrapped注解适用于反序列化和序列化,因此不需要额外的配置来支持使用该注解的字段的反序列化。
Jackson 2.13的Javadocs for @JsonUnwrapped明确指出该注解适用于反序列化和序列化:

用于指示属性应该被“展开”序列化的注解 - 即,如果它将被序列化为JSON对象,则其属性将作为其包含对象的属性包含在内,并且在反序列化时重新生成“缺失”的结构。

[...]

在反序列化时应用“包装”,以便可以读取序列化输出。


0

对于像我一样在谷歌上搜索并尝试解决反序列化未包装的 Map 问题的人,有一个解决方案,使用 @JsonAnySetter

public class CountryList
{

    Map<String, Country> countries = new HashMap<>();

    @JsonAnySetter
    public void setCountry(String key, Country value)
    {
        countries.put(key, value);
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接