https://kotlinlang.org logo
#http4k
Title
# http4k
k

King River Lee

12/06/2023, 8:34 AM
Copy code
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", shape = JsonFormat.Shape.STRING)
not work on LocalDateTime field of data class
d

dave

12/06/2023, 10:37 AM
For this, the problem is that the standard http4k mapping overrides any Jackson mapping for the type. I've not really used many of the annotations (so can't really help with the specifics of getting it working with them), but one way to fix this without annotations is to define your own marshaller:
Copy code
data class FooBar(val field: LocalDateTime)

object MyJackson : ConfigurableJackson(
    KotlinModule.Builder().build()
        .asConfigurable()
        .withStandardMappings()
        .text(StringBiDiMappings.localDateTime(DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm")))
        .done()
)

fun main() {
    println(MyJackson.asFormatString(FooBar(LocalDateTime.now())))
}
.. which will yield what you want:
Copy code
{
  "field": "2023-12-06 10:36"
}
k

King River Lee

12/06/2023, 12:29 PM
Ok. but I just use the special format in one handler. and others use default is ok.
I also disable the
Copy code
WRITE_DATES_AS_TIMESTAMPS
for jackson mapper.
d

dave

12/06/2023, 12:40 PM
you can do that in the construction of your Jackson as well.
Copy code
object MyJackson : ConfigurableJackson(
    KotlinModule.Builder().build()
        .asConfigurable()
        .withStandardMappings()
        .text(StringBiDiMappings.localDateTime(DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm")))
        .done()
        .configure(DeserializationFeature.WHATEVERFEATUREYOUWANT, true)
)
There are a few things going on here. http4k is overriding the serialization of the annotation with it's own mapping (which is in
.withStandardMappings()
. I don't know about the predecence of the custom mappings to the annotations for Jackson - it's all quite magical (which is why we don't try to use them). You could create a custom type which controls the serialisation
Copy code
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.KotlinModule
import dev.forkhandles.values.LocalDateTimeValue
import dev.forkhandles.values.LocalDateTimeValueFactory
import org.http4k.format.ConfigurableJackson
import org.http4k.format.asConfigurable
import org.http4k.format.value
import org.http4k.format.withStandardMappings
import org.http4k.lens.StringBiDiMappings
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class MyFunnyDateTime private constructor(value: LocalDateTime) : LocalDateTimeValue(value) {
    companion object : LocalDateTimeValueFactory<MyFunnyDateTime>(
        ::MyFunnyDateTime, fmt =
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
    )
}

data class FooBar(val field: MyFunnyDateTime)

object MyJackson : ConfigurableJackson(
    KotlinModule.Builder().build()
        .asConfigurable()
        .withStandardMappings()
        .value(MyFunnyDateTime)
        .text(StringBiDiMappings.localDateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
        .done()
        .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true)
)

fun main() {
    println(MyJackson.asFormatString(FooBar(MyFunnyDateTime.of(LocalDateTime.now()))))
}
k

King River Lee

12/06/2023, 12:50 PM
Yes,
annotation
is magic. So I will try your method. I will try less
annotation
in the furture. Thanks