-
-
Notifications
You must be signed in to change notification settings - Fork 175
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
Missing empty constructor issue: deserialization breaking change from 2.17 to 2.18 #846
Comments
Needs to be checked against 2.18.1 at least (ideally also 2.18.2-SNAPSHOT, build from 2.18 |
I can confirm the bug with these versions of jackson-module-kotlin:
I also tested with version 2.17.2 and the behavior to assure that the |
The root cause of this also seemed to be the same as #841 (FasterXML/jackson-databind#4777). I first checked how the On the other hand, as a result of |
@baylrock Please include actual exception message (with at least some of the stack trace). |
It looks like intent was for Constructor to use "Delegating" mode; and if so perhaps it is necessary to use annotation
since I don't see any good heuristics for databind to determine this intent (constructor parameter name and underlying property. Not sure why in 2.17 that would be mode selected. EDIT: Actually, I do have a guess. Perhaps it is due to type of single-argument being |
@cowtowncoder issue was found when migrating from 2.12 to 2.18. So it shouldn't be about 2.17 being weird. |
@baylrock That is assuming behavior as of 2.17 was correct, which while not unreasonable assumption is not always true. In case of refactoring of property introspection for 2.18, logic was rewritten to address actual flaws for some well-known cases, but making sure all unit tests pass. Problem here is that there is an unlimited number of combinations, edge cases, and so coverage is always incomplete. While case presented here is not very complex, it seems likely it wasn't covered, and change in logic was not detected. The question, then, is which of behaviors is more correct: that of 2.17, or that of 2.18. Having said that, I do now have one idea wrt why Creater mode heuristics may have changed with 2.18 -- I vaguely remember there being some logic to consider some types (specifically But with all of this said: I would suggest adding explicit
(with whatever mechanism Kotlin requires) |
I take the liberty and step in for baylrock, 'cause I just happened to see the updates to this ticket now. This is the exception when instantiating class
Also, annotating the constructor, as you described, with…
…made the exception go away 🥳 (anyway, my problem turned out to not being the one described here 😊). Thank you cowtowncoder for helping us along! |
I've stepped onto this issue too, but in a slightly different case. I assume the root cause is the same.
I am wondering the same. It seems the current behavior is more in line with pure Jackson without Kotlin module. I've tested normal Java classes and records and in both versions they failed to deserialize if there was no Anyway, it's a bit counter-intuitive that If the current behavior of 2.18 is considered valid, it should probably be documented as a breaking change in 2.18 to help people migrate. |
Quick note: missing Not sure that helps untangle the issue but thought I'll mention it. |
We upgraded to spring boot 3.4 that uses jackson-core 2.18.0 and the existing code broke with the error. When will this issue be fixed?? It's forcing all the applications that went through upgrade to have the empty constructors only work fine :( https://github.com/aishanand/personal- Github code space to recreate the issue
[Note:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes that uses 2.18.0] |
Have you tried 2.18.2?
…On Wed, Jan 15, 2025 at 2:58 PM aishanand ***@***.***> wrote:
We upgraded to spring boot 3.4 that uses jackson-core 2.18.0 and the
existing code broke with the error. When will this issue be fixed?? It's
forcing all the applications that went through upgrade to have the empty
constructors only work fine :(
https://super-duper-giggle-97gv6p6x5ggf9pgp.github.dev/ - Github code
space to recreate the issue
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
construct instance of com.jackson.issue.deserialize.dto.FruitDTO(although
at least one Creator exists): no String-argument constructor/factory method
to deserialize from String value
('{"name":null,"flavorDTO":{"color":"yellow","taste":"sweet","smell":{"smellsGood":true}}}')
at [Source: UNKNOWN; byte offset: #UNKNOWN] at
com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4636)
at
com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4567)
at
com.jackson.issue.deserialize.DeserializeApplication.main(DeserializeApplication.java:18)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot construct instance ofcom.jackson.issue.deserialize.dto.FruitDTO
(although at least one Creator exists): no String-argument
constructor/factory method to deserialize from String value
('{"name":null,"flavorDTO":{"color":"yellow","taste":"sweet","smell":{"smellsGood":true}}}')
at [Source: UNKNOWN; byte offset: #UNKNOWN] at
com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at
com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1754)
at
com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1379)
at
com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:311)
at
com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1592)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:197)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
at
com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4631)
image.png (view on web)
<https://github.com/user-attachments/assets/04f15613-61b4-4790-b280-0ea4e8a31202>
[Note:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes
that uses 2.18.0]
—
Reply to this email directly, view it on GitHub
<#846 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAANOGMFFLVMOPS65EUMZXT2K3R2TAVCNFSM6AAAAABROYIUGSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKOJUGEYDONBQHE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@cowtowncoder |
Ah. I only saw the email notification and replied without reading the context. As to fix, it is not clear behavior can or will be changed. But instead of adding an empty constructor (which really shouldn't be needed) please considering adding annotation -- something I have mentioned multiple times in this thread:
on constructor. That will indicate that the incoming value should match the full argument value of 1-arg constructor, and not 1 property of JSON Object with name matching that argument. I will also file an issue on |
Ok the issue I created on databind side does not seem to capture actual issue. Reading through comments here there may even be multiple different problem cases. But fundamentally what would be needed would be Java translation of failing test case here, so I could see what is going on and perhaps how to resolve it. One case I did notice tho was the case with no annotations: Jackson 2.18 can only auto-detect But Kotlin module could detect things differently, by It looks like this already exists, but I guess it won't detect case(s) here. WDYT @k163377 ? |
@cowtowncoder |
Search before asking
Describe the bug
It appears that 2.18 introduced a change to the constructor detection, causing existing use cases to fail. I observed it in a case where a class extending a Map without an empty constructor can no longer be instantiated. See the test case example.
To Reproduce
With jackson 2.18.0 onboard:
Expected behavior
Changes should be backward-compatible per the versioning standard (minor version changed).
Versions
Kotlin:
Jackson-module-kotlin: 2.18.0
Jackson-databind: 2.18.0
Additional context
I'm not 100% sure if this is a Kotlin module issue or not, as I operate in Kotlin codebase only and not invested enough to test it in plane java.
Generally, the fix to the issue is simple; the questionable part is that, if this is intentional, this is technically a breaking change in a minor version change.
The text was updated successfully, but these errors were encountered: