Hi everyone, I'm consuming data from a JSON API. ...
# serialization
t
Hi everyone, I'm consuming data from a JSON API. Some responses contain decimal numbers. Depending in the culture-info field sent to the server, they might use dots (e.g. 18.312) or commas (e.g. 18,312) Is there some way I can interpret these both as Float in my Serializer class (Float only accepts dot notation)? Maybe through some custom field desserialization or something...?
j
you can create a custom serializer for example
t
A custom serializer can receive a String and return a Float? How would I use it after creating it?
Can a custom serializer for certain fields only?
Oh I think i get it, I create a custom serializer, then I create a Serializable class CustomFloat with that serializer, and the fields will be of that type,right?
Here you have a lot of examples
I would use a specific class for that
Do you need to handle that float in local?
Or you are only going to show that string in the UI?
t
No, I'm not showing that string in the UI. I rather have it saved only as a Float and deal with Internationalization locally
j
then if it is a "real" float, I would create a custom class for that, but ideally backend should solve that
t
Yeah but changing the backend is not an option, what you gona do 🥲
@Javier I have this
Copy code
object FloatAsDecimalString : KSerializer<Float> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Float", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: Float) =
        encoder.encodeString(value.toString())

    override fun deserialize(decoder: Decoder): Float =
        decoder.decodeString().replace(",", ".").toFloat()
}

@Serializable
data class ExampleResponse(
    val id: Long,
    val someDecimal: Float,
)
Now, how do I apply the Serializer?
j
Copy code
@Serializable
data class ExampleResponse(
    val id: Long,
    @Serializable(with = FloatAsDecimalString::class) val someDecimal: Float,
)
I think with that
t
Copy code
Json.decodeFromString<ExampleResponse>("""
    {
        "id": 1,
        "someDecimal": "1.31"
    }
""")
This gave me an error: java.lang.ExceptionInInitializerError at com.qmx.web.contract.response.ExampleResponse$$serializer.deserialize(Unknown Source:64) at com.qmx.web.contract.response.ExampleResponse$$serializer.deserialize(ExampleResponse.kt:24) at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:63) at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:33) at kotlinx.serialization.json.Json.decodeFromString(Json.kt:85)
j
this is working for me
I changed the Float inside PrimitiveSerialDecriptor
t
Why?
Wow it worked for me too changing to "id"
But why hahaha
j
I think because you cant use a type
you can change that to whatever you want,
sasdsadas
should work too
t
There's probably a better descriptor for this use case then maybe? I don't know anything about descriptors yet...
j
probably that Serial name will create some code under the hood, and using Float or whatever existent type or reserved words is not a good idea
I usually put the original property name, in this case I would put
someDecimal
,
t
I'll put DecimalString. I think it makes sense, its a DecimalString, which is a String, that's the description of the field i guess hahaha
Anyway, thanks a lot 🙌
🙂 1