-
-
Notifications
You must be signed in to change notification settings - Fork 177
On the priority of JsonCreator
and Constructor
#514
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
Comments
Oh, well that's pretty interesting—I, too, would expect the explicit annotation to win. This is likely controlled in jackson-databind, so @cowtowncoder might know of the top of his head. |
I also have a question about the behavior when defining multiple data class D1 @JsonCreator constructor(val foo: Int, val bar: String) {
@JsonCreator constructor(foo: Int, bar: Int) : this(foo, bar.toString())
}
data class D2(val foo: Int, val bar: String) {
@JsonCreator constructor(foo: Int, bar: Int) : this(foo, bar.toString())
companion object {
@JvmStatic
@JsonCreator
fun creator(foo: Int, bar: String) = D2(foo, bar)
}
}
data class D3(val foo: Int, val bar: String) {
companion object {
@JvmStatic
@JsonCreator
fun creator(foo: Int, bar: String) = D3(foo, bar)
@JvmStatic
@JsonCreator
fun creator(foo: Int, bar: Int) = D3(foo, bar.toString())
}
}
class CreatorTest {
val mapper = jacksonObjectMapper()
val src = "{\"foo\":1,\"bar\":2}"
@Test
fun t1() {
val expected = D1(1, "2")
// com.firstxml.jackson.databind.exc.InvalidDefinitionException is thrown.
assertEquals(expected, mapper.readValue(src))
}
@Test
fun t2() {
val expected = D2(1, "2")
// no errors thrown.
assertEquals(expected, mapper.readValue(src))
}
@Test
fun t3() {
val expected = D3(1, "2")
// com.firstxml.jackson.databind.exc.InvalidDefinitionException is thrown.
assertEquals(expected, mapper.readValue(src))
}
} This appears to be caused by a similar cause. |
@cowtowncoder Could you please take a look at this question? |
I wish I remembered original thinking on precedence of I suspect there is at least one unit test that tests this, too, if anyone has time to go and have a look. |
Here's another example of this being weird: interface Value<out T: Any> {
val raw: T
@JsonValue
fun toExternalForm() = raw
}
data class Id(override val raw: String) : Value<String> {
companion object {
@JvmStatic
@JsonCreator
fun create(raw: String): Id {
// We never get here. Debugging shows that the constructor is called, but if
throw IllegalStateException()
}
}
}
data class Id2(override val raw: String) : Value<String> {
companion object {
@JvmStatic // but no@JsonCreator
fun create(raw: String): Id2 {
return Id2(raw)
}
}
}
class JsonTest {
@Test
fun `Id doesn't call @JsonCreate method`() {
val mapper = jacksonObjectMapper()
val event = Id(UUID.randomUUID().toString())
val json: String = mapper.writeValueAsString(event)
assertEquals(json.length, 38)
assertEquals(event, mapper.readValue(json, Id::class.java))
}
@Test
fun `but Id2 fails without @JsonCreate`() {
val mapper = jacksonObjectMapper()
val event = Id2(UUID.randomUUID().toString())
val json = mapper.writeValueAsString(event)
val root = mapper.readValue(json, Id2::class.java)
}
} |
Note on the above if it helps anyone. The following works for Kotlin data classes @JvmRecord
data class Id
@JsonCreator(mode = DELEGATING)
constructor(override val raw: String) : Value<String> {
companion object {
fun mint() = Id(UUID.randomUUID().toString())
}
} |
FYI. Despite the above workaround, we've gone a different route for our Kotlin data classes. We've had some PRs merged into https://github.com/bertilmuth/moonwlker so that it now supports value types like the above data class without any annotations. |
If a
Constructor
and aJsonCreator
are defined that take the same type as an argument, as shown below, I felt that theJsonCreator
would take precedence.On the other hand, the following test shows that
Constructor
is given priority.Which takes precedence, the
JsonCreator
or theConstructor
?Also, if there is a document that shows what priority is given to
JsonCreator
asJackson
, it would be helpful.The text was updated successfully, but these errors were encountered: