Hello :wave: Any suggestions on how to write a cus...
# serialization
d
Hello 👋 Any suggestions on how to write a custom
KSerializer
that behaves similar to the built-in ones for primitives? e.g. I can deserialize
Double
from Number (Int/Float) or String representation
Copy code
var kotlinxDouble: Double = format.decodeFromString("""
    0
""".trimIndent())
println(kotlinxDouble)

kotlinxDouble = format.decodeFromString("""
    1.0
""".trimIndent())
println(kotlinxDouble)

kotlinxDouble = format.decodeFromString("""
    "2.0"
""".trimIndent())
println(kotlinxDouble)
tried
Copy code
object BigDecimalStringSerializer : KSerializer<BigDecimal> {

    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: BigDecimal) {
        encoder.encodeString(value.toString())
    }

    override fun deserialize(decoder: Decoder): BigDecimal {
        val raw = decoder.decodeString() // <-- blows up when not a String representation, i.e. on 0 and 1.0 values from above
        return BigDecimal(raw)
    }
}
Is there something like
decoder.getRawValue
or something like that?
Oh, you mean you want it to work with both
1
and
"1"
?
d
yeah
its part of a bigger problem that I'm trying to solve -> basically a field can be represented by any valid JSON primitive
the default behavior would be to read it as
String
and then try to coerce it to some specific value type
in Jackson I can use
@JsonCreator/@JsonValue
to achieve this e.g.
BigDecimal
example (end users provide the conversion logic to/from JSON using converter)
Copy code
data class BigDecimalWrapper(val value: BigDecimal) {
    @JsonValue
    fun rawValue() = converter.toJson(value) // can serialize to whatever format

    companion object {
        val converter: BigDecimalConverter = BigDecimalConverter()

        // can deserialize from Any
        @JsonCreator
        @JvmStatic
        fun create(rawValue: Any) = BigDecimalWrapper(converter.toScalar(rawValue))
    }
}
d
This should get you started.
Copy code
object BigDecimalStringSerializer : KSerializer<BigDecimal> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING)
    override fun serialize(encoder: Encoder, value: BigDecimal) {
        encoder.encodeString(value.toString())
    }
    override fun deserialize(decoder: Decoder): BigDecimal {
        val input = decoder as JsonDecoder
        val element = input.decodeJsonElement()
        val raw = element.jsonPrimitive.content
        return BigDecimal(raw)
    }
}
👍 1
d
works like a charm, thanks @Dominaezzz