FasterXML / jackson-module-kotlin

Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
Apache License 2.0
1.12k stars 175 forks source link

Data class serializing with standard lib works when number of properties > 1 (Spring Boot 3.1.2, Kotlin 1.9.0) #705

Closed jelle82 closed 1 year ago

jelle82 commented 1 year ago

Your question

Hi,

Not sure if this is an issue. But it is curious.

When using spring boot, when posting to an end point that takes in a data class that has more than 1 constructor parameter, eg:

data class Person( val foo: String, val bar: String, )

The jackson-module-kotlin is not necessary.

However, if I remove one of the parameter, eg:

data class Person( val foo: String, )

I get following error:

2023-08-20T16:57:51.270+02:00 WARN 1420 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance ofde.neozo.java2kotlin.Person(although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)]

Adding the jackson-module-kotlin 2.16 seems to solve this error. `

cowtowncoder commented 1 year ago

This is likely related to the ambiguity between 2 different possible interpretations for 1-argument constructor, to present either

  1. JSON Object with 1 property, like { "foo": "string" }
  2. JSON Scalar value (like 123 or "string")

either of which could map to constructor. This ambiguity does not occur with different number of arguments (since those must be multi-property JSON Objects). You can use @JsonCreator(mode = JsonCreator.Mode.DELEGATING) (and Mode.PROPERTIES) to change interpretation if auto-detected mapping is not what you want.

However: if the class you have is Kotlin class like here, you really should use Kotlin module -- Kotlin classes are not officially supported by core jackson-databind. They might work (as you've noticed). I think Kotlin module may use more advanced logic to figure out most likely interpretation -- or maybe it just defaults to what happens to work for you.