-
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
Boolean property name starting with 'is' not serialized/deserialized properly #80
Comments
Note that the following test succeeds as expected:
And finally, if another field is present (so a constructor can be matched) and
Here the assert fails. |
Encountered the same problem, |
I'm seeing this issue as well. One thing I noticed is that if I flip the val to a var, then it works as expected. So I'm guessing the issue is that the val generates a Java getter but not the setter, and that's what's causing the problem here. |
Jackson expects JavaBean naming patterns, Kotlin does not always generate things that way and therefore creates an unwinnable situation. I'm still looking at options, but there is a workaround for some cases. This works by adding a
|
If in Kotlin I have So I think it will be ok to add |
I have a similar problem for Boolean property when its name starts with
The error message says property |
We have encountered this thing as well. When we receive json that has a boolean, which starts with "is", then it fails on The funny thing is that when another property is added to data class, then it works flawlessly, e.g. Adding |
Another incarnation of the problem seems to be that
the property still gets serialized (as "wholeProjectExcluded"). A work-around is to write the code as
or shorter, as @Tapac points out, as
|
Just wasted a bunch of time tracking this down. Any plans to fix it? |
@sschuberth, you can use |
Thanks @Tapac, will use that! |
My code actually looks like this:
and it still serializes as |
@brokenthorn you need to use |
As @raderio has already mentioned, you need to use |
But why is this happening? There is no straight answer. Booleans even get compiled to fields in Java prefixed with "is". There is absolutely no reason to strip the "is", please fix this. |
Totally agree. This seems very inconsistent and makes implementing serialization from other platforms that follow a more expected format, harder. |
Oh my... |
Not sure why this would happen with Kotlin module, but core Jackson databind ONLY considers "is"-prefix for getters and setters -- field names (and constructor parameter names if available) are used as-is and do not infer any special handling. |
Could it be that a kotlin val/var has a auto generated getter/setter for Java compatibility purposes that is prefixed with "is"? For example, if I have a kotlin property "done", I believe it will generate a getter/setter where you can call isDone() from Java. |
Makes no sense then to remove the is part when something like isDone is defined in Kotlin, not Java. |
So I did a deep dive and figured out what was going on. My general assumption was mostly correct in that it was an issue with the generated getter/setters, although just in a slightly different way than I originally thought. The way that Kotlin works is that if you have a val boolean field isTrueOrFalse, Kotlin will generate a getter (and a setter if it's a var). For booleans, Kotlin appears to generate the getter/setters with the same name (it seems to skip adding the "is" prefix if the boolean field already is prefixed by "is"; interestingly, the same behavior does not appear to happen in non boolean getters where the field name starts with get). So now we are left with having both a field and method for a given property. Now inside the Jackson data bind code (so not part of kotlin module), there is logic to get rid of the field (BeanSerializaerFactory.removeIgnorableTypes), leaving only the method left. Now there is code later on to find the implicit property name. But because it's a method and not a field, it calls BeanUtil.okNameForIsGetter. This logic in turn strips out the "is" prefix because it's working under the standard Java naming convention for beans where the underlying field does not have the "is" but the getter does. So where does this leave us? I'm not sure what the best solution may be, but here's one proposal I'm currently testing locally that only requires changes to this module code.
What I am doing here is basically checking if there is a field with the same name as the method, then use the method name (without any name mangling). I've limited it to kotlin, boolean properties, and backed with a cache to keep the impact as small as possible and also for performance reasons since the check involves reflection. Note that my solution will ignore JsonProperty annotations explicitly setting it to a different name. However, from my testing, I've found that JsonProperty doesn't even work if you have a "isTrueOrFalse" property name with JsonProperty("foo") annotation (serializing works but deserializing fails). If you did want to honor the property, you could add a check of |
When will this be fixed? I still have this issue with 2.9.9 and is causing some unexpected behavior. |
@ElbowBaggins thanks! |
Merged @LipatovAndrey 's fix -- will be in 2.10.1 And also contemplating actually adding databind |
* jackson-module-kotlin changed the serialization behaviour for fields starting with 'is': FasterXML/jackson-module-kotlin#80 * jackson 2.10's objectMapper.convertValue() now converts everything even if the source is already from the target type. The fixed test was expected a value from a not fully converted Map.
* fix(templated-pipelines-v1): Expected artifacts correctly inherited/merged TemplateMerge.mergeDistinct() was merging 2 list of different types into one. Upcoming Jackson library update would have broken compilation of TemplatedPipelineModelMutator if left unmodified. * chore(dependencies): Upgrade Spring Boot to 2.2.1 Adjusting code for Jedis 3, Jackson 2.10 upgrades. * fix(artifacts): Always persisting `pipeline.expectedArtifacts.boundArtifact` Artifact resolution wasn't always persisting `pipeline.expectedArtifacts.boundArtifact` depending on the expectedArtifact's type when passed to `ArtifactResolver.resolveArtifacts()`. Only `ExpectedArtifact` would get their `boundArtifact` updated; if a Map was used then a copy of that Map would be updated instead and this isn't returned to the caller. The update of Jackson to 2.10 made it so that `boundArtifact` would always be updated on a copy of the passed `expectedArtifact` no matter its type, this commit is an attempt to fix both problems. A better fix would be to make it clear what type is accepted and expected, but that's a much larger refactor. * chore(dependencies): Upgrade Spring Boot to 2.2.1 cont'd * jackson-module-kotlin changed the serialization behaviour for fields starting with 'is': FasterXML/jackson-module-kotlin#80 * jackson 2.10's objectMapper.convertValue() now converts everything even if the source is already from the target type. The fixed test was expected a value from a not fully converted Map. * chore(dependencies): bump kork and keiko
|
keys - the jackson lib in Spring Boot 2.2.1 serializes booleans like: isCertificateAuthority => certificate_authority - but this behavior will be changed in Spring Boot 2.2.4's jackson lib: FasterXML/jackson-module-kotlin#80 - this commit makes the code work for both current & future versions of jackson lib
@cowtowncoder I thought this would be fixed out of the box for jackson-module-kotlin 2.11 but I am using the latest stable version |
Have you tried to add jackson-databind module as well?) It will cause an issue without it(
|
Yes, both Kotlin module and jackson-databind would need to be 2.11(.2). |
Hi,
I'm experiencing issues with a boolean property which name starts with 'is'.
While the getter doesn't get prefixed by kotlin, it seems that jackson still strips away 'is' as though it was a prefix. The resulting json doesn't contain the 'is', and deserialization fails.
This test illustrates the problem:
This fails on
mapper.readValue(..)
with:The text was updated successfully, but these errors were encountered: