Deserialize missing value of `EXTERNAL_PROPERTY` type using custom `NullValueProvider`
See original GitHub issueIs your feature request related to a problem? Please describe.
I am currently trying to deserialize a structure with a generic field that has an external type property, where the type property is always present, but the actual property may be absent, in which case it should just use a custom NullValueProvider
.
The json can either look like this:
{
"type": "inner-implementation",
"value": {
"foo": "bar"
}
}
Or like this, in which case value
should use the NullValueProvider
:
{
"type": "inner-implementation"
}
The outer type looks like this:
public class Wrapper<I extends Inner> {
@JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY)
private I value;
public Wrapper(@JsonProperty(value = "value", required = true) I value) {
this.value = value;
}
}
And the inner types all implement this interface:
@JsonSubTypes({
@Type(InnerImplementation.class),
})
public interface Inner {}
With an implementation of the inner type looking like this:
@JsonTypeName("inner-implementation")
@JsonDeserialize(using = InnerImplementationDeserializer.class)
public class InnerImplementation implements Inner {
@Nullable
private String foo;
public InnerImplementation(@Nullable String foo) {
this.foo = foo;
}
}
Each implementation of Inner
also has a deserializer which implements the getNullValue
method:
class InnerImplementationDeserializer extends StdNodeBasedDeserializer<InnerImplementation> {
protected InnerImplementationDeserializer() {
super(TypeFactory.defaultInstance().constructType(InnerImplementation.class));
}
@Override
public InnerImplementation convert(JsonNode root, DeserializationContext ctxt) throws IOException {
JsonNode foo = root.get("foo");
return new InnerImplementation(foo != null ? foo.textValue() : null);
}
@Override
public InnerImplementation getNullValue(DeserializationContext ctxt) throws JsonMappingException {
return new InnerImplementation(null);
}
}
I have also disabled FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
.
The first snippet deserializes without problems, and when I remove required = true
from the value property, the second snippet deserializes with Wrapper#value
being null
. With required = true
however, a com.fasterxml.jackson.databind.exc.MismatchedInputException
is thrown.
The exception originates from this part of the jackson databind codebase.
Describe the solution you’d like
In the linked snippet of jackson code, it would in my opinion be appropriate to use the custom NullValueProvider
s if FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
is disabled.
Usage example
The feature would work like shown above, however depending on how reasonable this approach generally is, the option FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
could be disabled by default.
Additional context
The underlying WRAPPER_ARRAY
property used in the background by EXTERNAL_PROPERTY
was already changed to support this behaviour: https://github.com/fasterxml/jackson-databind/issues/2467
Issue Analytics
- State:
- Created a year ago
- Comments:6 (6 by maintainers)
Given that the
ExternalTypeHandler
just “fakes” an array structure, and the deserializer forEXTERNAL_PROPERTY
then just extends the one forWRAPPER_ARRAY
and inherits all its behavior, including https://github.com/FasterXML/jackson-databind/issues/2467 (which is basically the same issue as this one, just for arrays), this is already supported by the deserializer. In the absent case, theExternalTypeHandler
just needs to not write the second field of the array, like I already tested here: https://github.com/fxshlein/jackson-databind/commit/a965ec73bc15302aad9d4edbe7bdcc784c5675a2Merged, will be in 2.14.0.