Closed MartinHaeusler closed 1 year ago
I just figured out that this only happens if the field name starts with is
. On all other field names, the @JsonProperty
annotation is respected as intended.
This problem is extra extra confusing when using an event based framework like Axon with Kotlin. A boolean with is in the name will always come out false inside of the event since Axon uses Jackson internally to serialize and deserialize events.
This turned out to be a huge waste of time until one of us remembered this was a known issue. Is there any plan to fix this problem?
I am not aware of anyone working on the issue. New contributors to Kotlin module would be highly appreciated, as its usage has been increasing rapidly along with adoption of Kotlin. But I don't personally have enough foundational knowledge of Kotlin as platform to be of much help unfortunately. I could try a Bat Signal on mailing lists, but I have rarely had much success when asking for something other than very specific help (f.ex I did get contributors to help with Scala module release). Ownership is something that you can't really sell or advertise for.
Same! Any solution? I thought that I made mistake somewhere in the configuration.
My code:
data class PlayerResponse(
@JsonProperty("abc")
val accountId: Long,
@JsonProperty("def")
val isAdmin: Boolean,
@JsonProperty("ghi")
val isConnected: Boolean
)
val mapper = jacksonObjectMapper().apply {
registerModule(ParameterNamesModule())
registerModule(Jdk8Module())
registerModule(JavaTimeModule())
}
val json = mapper.writeValueAsString(PlayerResponse(1, true, true))
Response:
{"abc":1,"admin":true,"connected":true}
The only workaround I've found is to rename the field in your (data) class, and then expose it with @JsonProperty
like so:
data class MyDTO(
@JsonProperty("isConnected")
val connected: Boolean // do NOT call this "isConnected"!
)
That worked for me, YMMV.
Same! Any solution? I thought that I made mistake somewhere in the configuration.
My code:
data class PlayerResponse( @JsonProperty("abc") val accountId: Long, @JsonProperty("def") val isAdmin: Boolean, @JsonProperty("ghi") val isConnected: Boolean ) val mapper = jacksonObjectMapper().apply { registerModule(ParameterNamesModule()) registerModule(Jdk8Module()) registerModule(JavaTimeModule()) } val json = mapper.writeValueAsString(PlayerResponse(1, true, true))
Response:
{"abc":1,"admin":true,"connected":true}
Use @get:JsonProperty("abc") and @param:JsonProperty("abc") annotation on Boolean field instead of @JsonProperty("abc")
@MaksimRT - wow it works. Thanks a lot!
@MartinHaeusler does the workaround as mentioned by MaksimRT a few posts up solve your issue as well?
I didn't try it, but it does seem plausible that it could fix the issue. The real question is: where does it come from, and can it be fixed rather than worked around? This is a very nasty bug after all, and extremely hard to search for on google, because likely you wouldn't even know what hit you.
It will be fixed in 2.10.1 version by https://github.com/FasterXML/jackson-module-kotlin/pull/256
@MartinHaeusler We are trying to find a way to deal with where annotations are placed and how they are interpreted, the issue is that Kotlin compiler chooses where they go, and it picks a spot that is far from good in terms of Jackson seeing them and being able to interpret them correctly.
I am looking to see if there are options to "imply" them where the are missing, or see if we can get Kotlin to consider placing them not in the "first" place it finds that matches their list, but ALL places we want them.
So it is more of incompatibility with Kotlin annotation targetting than a bug in Jackson Kotlin module. When the annotations are where we can see them safely, things work. If they end up going somewhere silly, not so much.
It is a current issue we want to solve for sure.
@MartinHaeusler
@erika33 yes?
Thanks @MaksimRT
Just adding @get:JsonProperty("abc") worked for me.
I did not add @param:JsonProperty("abc") and it still worked. Is there any specific reason why you added @param:JsonProperty("abc") as well?
Thanks @MaksimRT Just adding @get:JsonProperty("abc") worked for me. I did not add @param:JsonProperty("abc") and it still worked. Is there any specific reason why you added @param:JsonProperty("abc") as well?
Hi, you are welcome)
What version of the library do you use?)
Changing @JsonProperty("fieldname") to @field:JsonProperty("fieldname") resolves the issue for data classes' "is" (Boolean) properties.
I have checked the following code and it seems to have already been resolved, so this issue is closed.
import com.fasterxml.jackson.annotation.JsonProperty
data class PlayerResponse(
@JsonProperty("abc")
val accountId: Long,
@JsonProperty("def")
val isAdmin: Boolean,
@JsonProperty("ghi")
val isConnected: Boolean
)
fun main() {
val mapper = jacksonObjectMapper()
val json = mapper.writeValueAsString(PlayerResponse(1, true, true))
println(json)
}
Hi,
I've got a data class with a boolean property called
isPublic
. This property needs to be called exactly like that in JSON. However, since the property name starts withis
, the prefix is stripped from the name. Adding@JsonProperty("isPublic")
does not work either:... fails with an assertion error:
java.lang.AssertionError: Expected <{"isPublic":true}>, actual <{"public":true}>.
It doesn't matter what you pass into the
@JsonProperty
annotation, in the JSON output the field is always (!!) calledpublic
.