java/jackson - @JsonValue/@JsonCreator 和 null

java/jackson - @JsonValue/@JsonCreator and null

我有一个 Value class 包含一个值:

public class Value {
    protected final Object value;

    @JsonValue
    public Object getValue() {
        return value;
    }

    @JsonCreator
    public Value(final Object value) {
        this.value = value;
    }
}

Value class 作为字段(在其他字段中)嵌入到数据 class:

class Data {
    protected final Value value;

    @JsonProperty("value")
    public Value getValue() {
        return value;
    }

    ...

    @JsonCreator
    public Data(@JsonProperty("value") final Value value, ...) {
        this.value = value;
        ....
    }
}

当输入 JSON 对 data 对象的 value 字段有 null 时(参见下面的示例),Data.value 为空。我想将 Data.value 设置为 new Value(null)。也就是说,数据对象必须持有一个非空值对象,它持有的是null。

{
  "value" : null,
  ...
}

实现此目的最简单的方法是什么?我当然可以更改 Data 的构造函数,但我想知道 Jackson 是否可以自动解决这个问题。

您可以编写自定义反序列化程序并根据您的要求覆盖 getNullValue() 方法,例如

public final class InstantiateOnNullDeserializer
    extends JsonNodeDeserializer
{
    @Override
    public JsonNode getNullValue()
    {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.convertValue(new Value(null), JsonNode.class);
        return node;
    }
}

并将其注册到您的 Data class

的值字段
class Data {
    @JsonDeserialize(using = InstantiateOnNullDeserializer.class)
    protected final Value value;


    @JsonProperty("value")
    public Value getValue() {
        return value;
    }



    @JsonCreator
    public Data(Value value) {
        this.value = value;
    }
}

请注意,您需要删除 @JsonProperty("value") 以避免参数类型不匹配。通过删除 JsonProperty 注释,您创建了一个所谓的 "delegate creator", Jackson 将首先将 JSON 绑定到参数的类型中,然后调用创建者

我认为如果不创建自己的反序列化器或修改构造函数(或 @JsonCreator),这是不可能的。

来自a good old thread in the Jackson User Group

@JsonProperty does not support transformations, since the data binding is based on incremental parsing and does not have access to full tree representation.

因此,为了避免自定义反序列化器,我会按照以下方式做一些事情:

@JsonCreator
public Data(@JsonProperty("value") final String value) {
    this.value = new Value(value);
}

这与你问的有点相反 ;)