https://kotlinlang.org logo
#getting-started
Title
# getting-started
n

nkiesel

09/09/2021, 8:41 PM
I am trying to serialize (and eventually deserialize) a
koltin.time.Duration
property of a data class in Kotlin 1.5.30 using Jackson 2.12.5. One immediate problem is that - because Duration is a value class - Jackson sees just a long value and thus serializes a
Duration.seconds(10)
as
20000000000
. This is obviously not what I want because it exposes the internal "use high bit to differentiate nano from milli". I tried to register a custom serializer which extends
JsonSerializer<Duration>()
using
@JsonSerialize
but that is ignored (presumably because Jackson just sees a long value). The only way I see right now is to have an explicit
durationAsString
property and keep that in sync with the
duration
property. Is there a better way? Note: I think I cannot use Kotlin serialization because this is part of a mixed Java/Kotlin project. But if I could: would that solve the issue?
e

ephemient

09/09/2021, 8:44 PM
it could work in kotlinx.serialization, but there isn't a serializer for kotlin.time.Duration built in
using Jackson's `@JsonSerialize`/`@JsonDeserialize` to customize how each field is serialized should work
this also seems to work:
Copy code
@ExperimentalTime
data class Foo(
    @get:JsonIgnore
    val dur: Duration
) {
    @JsonCreator constructor(
        @JsonProperty("dur")
        dur: String
    ) : this(Duration.parse(dur))
    @get:JvmName("getDur")
    val _dur: String get() = dur.toString()
}
n

nkiesel

09/09/2021, 9:27 PM
I tried `@JsonSerialize`/`@JsonDeserialize` but could not make that work. However, the 2nd solution does work for me. Thanks a lot!
BTW: I could also make
kotlinx.serialization
work by creating a
object DurationAsStringSerializer : KSerializer<Duration>
and annotating the property with
@Serializable(with = DurationAsStringSerializer::class)
. This looks cleaner (and easier to replicate) than the `@JsonIgnore`/`@JsonCreator`/`@JsonProperty`/`@JvmName` approach. I will see if using
kotlinx.serializatin
is really not an option for my project.
e

ephemient

09/09/2021, 9:54 PM
if it's repeated, you can use
@file:Serializers(DurationAsStringSerializer::class)
once at the top of the file, which is equivalent to adding
@Serializable(with = ...)
at every occurrence of
Duration
n

nkiesel

09/09/2021, 11:07 PM
Yeah. Ideally, the jackson-kotlin module will add custom serializers for Kotlin stdlib-specific types (and especially value/inline classes like
Duration
)
e

ephemient

09/09/2021, 11:14 PM
Duration is tricky because it's an inline class, so it appears as a long with a mangled name to Java
n

nkiesel

09/09/2021, 11:25 PM
yeah. But so are all inline/value classes. Which is why I hope we will get built-in support for these.
Duration
is especially tricky because it uses bit manipulation to encode type information (nanos vs. millis).
e

ephemient

09/09/2021, 11:30 PM
https://github.com/FasterXML/jackson-module-kotlin/issues/413 all the inline stuff is effectively invisible to Java