简体   繁体   中英

java/jackson - @JsonValue/@JsonCreator and null

I have a Value class which holds a value:

public class Value {
    protected final Object value;

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

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

This Value class is embedded as a field (amongst other fields) in a data 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;
        ....
    }
}

When the input JSON has null for the value field of a data object (see below for example), Data.value is null. I would like to have Data.value set to new Value(null) . In other words, the data object must hold a non-null value object, which holds the null.

{
  "value" : null,
  ...
}

What is the easiest way to achieve this? I could ofcourse alter the constructor of Data , but I am wondering if Jackson could resolve this automatically.

You can write a custom de-serializer and override the getNullValue() method according to your requirements eg

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;
    }
}

and register it on the value field of your 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;
    }
}

Note that you need to remove the @JsonProperty("value") to avoid argument type mismatch. By removing JsonProperty annotation you create a so-called "delegate creator", Jackson will than first bind JSON into type of the argument, and then call a creator

I do not believe that this is possible without creating your own deserializer or modify the constructor (or @JsonCreator ).

From 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.

So, in order to avoid a custom deserializer I would do something along the lines of:

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

Which is kind of the opposite of what you asked ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM