-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
There seems to be a difference in behavior when deserializing JSON into an object via a Builder when that Builder has a @JsonCreator
method on it when that method takes a primitive vs an array.
Consider a pojo class like this:
private static final class TestBean {
public int getI() {
return _i;
}
private TestBean(final Builder builder) {
_i = builder._i;
}
private final int _i;
}
Then consider a Builder for the pojo that supports deserialization value from a value as well as an object (or via code calling setX
):
public static final class Builder {
public Builder() { }
@JsonCreator
public Builder(final Integer value) {
_i = value;
}
public void setI(final Integer value) {
_i = value;
}
private Integer _i;
}
This combination can be deserialized from {"i":3}
and from 3
.
However, if we instead declare a @JsonCreator
method that accepts a List<Object>
then the deserialization is only supported from [3]
and not from {"i":3}
. For example, replacing the above @JsonCreator
annotated constructor with:
@JsonCreator
public Builder(final List<Object> jsonArray) {
setI((int) jsonArray.get(0));
}
This appears to be because in BeanDeserializerBase.java#L222 the value of _vanillaProcessing
is set based in part on the value of _nonStandardCreation
which considers _valueInstantiator.canCreateUsingArrayDelegate()
but does not consider instantiation from a primitive value to be "non standard creation".
I am not sure which is the desired behavior. That is, it is an over-sight that with a @JsonCreator
accepting a value that the same pojo can be deserialized from an object OR whether the array case should also support deserialization from an object.
In the case that we don't want the flexibility - and it seems reasonable that if you declare a @JsonCreator
that this how the object should be built from JSON - then fix would be to include canCreateFromXXX
for the various primitive types in the computation of _nonStandardCreation
; although I am unclear on what the broader implications of this migh be.
In the case that we want to allow creation of objects from both an alternate representation (e.g. array or primitive) as well as from an object representation then we need a more fine-grained check when delegating to the vanilla path. In particular, we should go down that path if there is non-standard only because of an array delegate (but it's an object representation in json). This will likely lead to evaluating the "vanilla-ness" of a particular deserialization based at deserialization time instead of upfront.
Jackson Version: 2.10.0