I have this simple data class. What should I do to...
# getting-started
p
I have this simple data class. What should I do to make it possible to use jackson to (de)serialize from-to json? I'd prefer not to specify property names explicitly.
Copy code
data class MyClass  @JsonCreator constructor (
    var changedAt: Date,
    var from: Int,
    var to: Int,
    var percentChanged: Int,
    var levelUsed: Int,
)
s
Just to check—have you installed the Jackson Kotlin module?
If you have, I would expect data classes to work out of the box. You shouldn't even need the
@JsonCreator
annotation.
If you're still having trouble, try #jackson-kotlin.
p
You mean this one?
👌 1
Without any annotation I get
These are the actual content of the classes
s
As well as adding the
jackson-module-kotlin
dependency, it also needs to be registered when you create the object mapper. Maybe that's missing?
If you have something like
val mapper = jacksonObjectMapper()
, that's using the Kotlin module and you're good 👍. But if you just have
val mapper = ObjectMapper()
, with no extra Kotlin module being registered, that could definitely explain the issues you're seeing.
(Don't ask me why the functions are named that way, it's confusing to me too)
p
Yesss, that was it.
s
🎉
🙏 1
p
It's a spring boot project.
And I'm actually mapping jsonb fields from-to Map<String,Any> to data classes.
s
Hm, that's interesting, I would expect Spring boot to configure the Kotlin module by default in its injected object mapper. Though that wouldn't help if you're creating your own separate instance I suppose.
p
Is there a good pattern to do the conversion? Or is it possible to map to dataclasses the jsonb fields? Now I map myself through an extension method, but that kind of painful and I cannot access the ObjectMapper bean, since using it from a companion object.
I would do the conversion to Entity level, that's why I choose the extension method
s
Sure, if you're using a recent version of Spring Boot with Hibernate 6, you should be able to map JsonB fields directly to entity classes
I think you would use the
@JdbcTypeCode
annotation, but I've not done it myself
Although it seems like there might be an open issue that stops it working totally seamlessly https://github.com/spring-projects/spring-boot/issues/33870
p
What would be the JdbcTypeCode of that field?
s
Again, I'm guessing, but:
@JdbcTypeCode(SqlTypes.JSON)
p
Oh, it works. Btw started converting an old java spring project to kotlin. Amazing how much boilerplate one can avoid 🤐
very nice 1
On the other hand, if the json is big, it can take quite a bit of time to parse it. Can one make it lazy?
t
you should (imo) almost never declared an object mapper bean yourself, spring boot configures it for you, check
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
you should need to define custom module and/or special configuration, eg if you want to configure the kotlin module:
Copy code
@Bean
  fun kotlinModule(): KotlinModule = KotlinModule.Builder()
      .configure(KotlinFeature.NullIsSameAsDefault, enabled = true)
      .build()
p
Huh, what does that Bean definition does? 🤔
t
tl;dr spring boot provides a lot of pluggable configurations, in case of jackson there are modules that you can add to customize the object mapper that spring creates for you. so
Copy code
@Bean
fun objectMapper() = jacksonObjectMapper()
completely overrides the whole logic spring gives you to configure the object mapper flexibly: https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.spring-mvc.customize-jackson-objectmapper
👍 1
also, personal preference, jackson is very smart on its own, I would rather do
ObjectMapper().findAndRegisterModules()
over
jacksonObjectMapper()
, jackson will scan the classpath and preconfigure the object mapper accordingly