-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Builder Deserialization with JsonCreator Value vs Array #2486
Comments
I think I will need bit more detail just to make sure, since I can make the test pass:
Primitive (well, "small set of scalars" really, int/Integer, long/Long, boolean/Boolean, String) creators should be fine even in "vanilla" processing. |
Can not reproduce currently; may be reopened with a test. |
I created what I think are tests demonstrating this issue: Let me know if I've missed something, and apologies for going MIA for so long. This is a great project and ends up as a dependency in just about every project I ever undertake. |
Thanks! No problem wrt time delay; I have no problem re-opening active cases, just want to actively manage active case list (since 300+ issues are hard to keep track off) |
Ok, I'll have to see but my first impression here is that this might be unsupported and unsupportable case: that is, you can not have both array-delegating and "regular" delegating creators. At least currently this is the case: only one can be used. Error message is misleading, of course, so at very least would be good to see if that could be improved. But... I will double-check if my thinking on exclusivity (delegating vs array-delegating) is or is not valid. I may be forgetting something here. |
I'm assuming "deleting" refers to === What concerns me is the inconsistent impact of the creators based on type on the normal (non- While I like the idea of being able to specify an alternate creation path while still retaining the object deserialization semantics, the inconsistency was surprising. Should At least documentation and a clearer error message would be advisable. It's been a while since I dove into it, but as I mentioned above and in the review, on the surface it would seem possible to address this if the vanilla-ness of the deserialization were deferred until the shape of the input were determined. Specifically, the deserialization is vanilla unless the input shape matches the creator argument shape (object => map, array => array/list, primitive => primitive). Not sure what the consequences of deferring this decision are. |
side note: created #2707 and implemented it; but since it is visible API change (sort of), has to go in 2.12.0. |
@vjkoskela Looking at this bit more, I think I now understand the mechanism. And it is not quite what I expected. Basically, there are couple of different classes of creators for POJOs, added in roughly this order over time
Of these, 1 and 4 are mutually exclusive: you can not have both delegating and traditional default constructor with setters approach, only one. Having said all that, I will see if it would actually be possible to support intended usage here. It seems possible that maybe combination might be supportable. In addition, this gives me some ideas of how to maybe improve the handling for 3.x (if not earlier). Division in many cases is by "shape" of incoming type, and maybe one could annotate |
Interestingly enough, just commenting out array-delegation as indicate, like so:
makes test pass, does not cause new failures with existing tests. I will have to go through code with more thought to see what other implications there might be but this might be easy to solve, for particular case here. |
That would be amazing! When I originally read the code, I was surprised at the complexity, but years of incremental additions have a way of doing that! -- totally understandable. If you come up with a path forward for 2.x please post here, I may have some cycles over the next few weeks to take a look. I'm back in Java land for a while and certainly if I run into this again it would give me a reason to invest some cycles. For context, the specific use cases that brought this up were extending two existing serialization models from primitive (case 1) and array (case 2) to object. So we created an object to represent the new model in each case, and added I also updated the tests, looks like you did too - thank you - and they now include variants that do not deserialize through the Builder (just into it) and behave the same way. So I don't think that the deserialization through the builder is related. |
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:
Then consider a Builder for the pojo that supports deserialization value from a value as well as an object (or via code calling
setX
):This combination can be deserialized from
{"i":3}
and from3
.However, if we instead declare a
@JsonCreator
method that accepts aList<Object>
then the deserialization is only supported from[3]
and not from{"i":3}
. For example, replacing the above@JsonCreator
annotated constructor with: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 includecanCreateFromXXX
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
The text was updated successfully, but these errors were encountered: