-
-
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
Deserializing to single-value Record from scalar values #2980
Comments
Ok so this is a common stumbling block: you are assuming that constructors would be taken as "delegating" creator, for 1-argument case. Unfortunately:
So this is working as intended from my perspective. To use delegating style you will need to add |
However... it does not look like there is a proper test for verifying ability to use delegation so I will add one to verify it actually works. :) |
And what do I know: the test case fails. So somehow constructor annotation is not being found; possibly same as or related to #2974. |
... except that my test was faulty; when fixed, works as expected. Should always double-check tests when they fail. |
Ok, so: I think this is working as expected: by default, Records will use "properties"-style construction. To use delegating-style with Records on 2.12 and later, necessary annotation will be:
since there is no shorter way to annotate primary constructor (as far as I know). |
Thanks very much for answering this in great depth 💐 |
@bfncs Yeah, this wasn't something I had thought of until you reported it; I did not realize Records were already used, although it was mentioned as something that sort of works (when discussing initially addition of explicit support for 2.12). I will add a note on 2.12 release page: thank you for bringing this up. |
One more thing just now came to my mind: this also works with a record's compact constructor and is a bit less boilerplate: record MyValueRecord(String value) {
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public MyValueRecord {}
} |
Interesting, did not know such shortcut was available. Thank you for sharing! |
I wanted to report that I came across this issue because a class → record migration lead to this (mysterious) failure. In my case it required backing out of the changes, because the type in question existed in a module that did not depend on Jackson, so adding the annotation was not an option. I think the current behavior is really unfortunate, and I hope the behavior can be fixed in Jackson 3.0. :-/ Thanks! |
@soc It is possible to add annotations to classes in other modules through the mixin feature. I'm not sure how it interacts with records, though. |
Thanks, I didn't know about this feature! (Keeping the class and the mixin in sync may create more work than it is worth in my case though.)
With records not even a custom deserializer worked. I reverted things back to a class and things are converting again. |
Quick note: use of custom deserializer for Record types should absolutely work. Although I suspect it depends on how you are registering custom deserializer (there are some general issues wrt annotation unification across Constructor parameters vs fields/getters/setters). Mix-in handling is general so it should work, but could have similar issues with annotation merging between Constructor parameters, other accessors. As to changing behavior: unfortunately I think that the way Records work is the "Right" way -- default without annotation should probably be Properties-based. Explicit annotation would be needed for delegating case. |
I will investigate further. I have cases where it works and cases where it doesn't.
Agree in that. I hope it can be changed for classes in Jackson 3 to work the same for classes as it currently does for records. Is there any documentation on property-based vs. delegation-based serialization? I searched the documentation, but couldn't find more information on it. Same for "creators" – I know that there are some "special" method names like Please let me know, if there isn't any, I'd be happy to write it, because I keep forgetting the details. |
Further debugging:
Surprisingly, it fails with a complaint on a type that doesn't even have the offending record:
|
@soc Alas, no documentation exists that I know of. Would be happy to add under Every now and then we have discussions on mailing lists, ideas, but it all really needs (at least) one person to kind of define structure, skeleton, over which content can be added. To me at least it is much easier to incrementally add bits and pieces when scaffolding is there. |
@soc That unrelated reference case is pretty odd, agreed. I would still be particularly interested in explicit deserializer case, if you can show how you are adding it. That might be an easy fix. I really, really hope I can find time to tackle Record handling: my first goal was actually to tackle #3352 for future compatibility. But beyond that there is the big need to resolve introspection which affects POJOs as well -- it just happens to be that for I really appreciate your help here & wish I could devote more time here. But let's keep things going at whatever rate we can. |
Hey @cowtowncoder, no worries! Nobody has unlimited time, power or focus. Thanks for all the work you do, and if people think more should be done ... they need to step up themselves! |
Describe the bug
I experience a potential regression since
2.12.0
when trying to deserialize a scalar value to a single-valueRecord
. Consider this test case:This works as expected in
2.11.3
, since2.12.0
aMismatchedInputException
is thrown:This still works as expected if an explicit factory method annotated with
@JsonCreator
is provided for the Record or for an equivalent Class without explicit@JsonCreator
(see additional test cases). I would expect the behavior for Records to be the same as for Classes, it also seems contrary to the brevity of Records to have to define an additional factory method.Version information
2.12.0
To Reproduce
See test case above.
The text was updated successfully, but these errors were encountered: