Kotlin Serialization: How to serialize MutableStateFlow<Float>?

Viewed 328

I have the following code

@Serializeable
class Car {
   val speed = MutableStateFlow<Int>(0)
   var isMoving: Boolean = false
}

The question is how to serialize MutableStateFlow?

2 Answers

Create a custom serializer for MutableStateFlow:

class MutableStateFlowSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<MutableStateFlow<T>> {
    override val descriptor: SerialDescriptor = dataSerializer.descriptor
    override fun serialize(encoder: Encoder, value: MutableStateFlow<T>) = dataSerializer.serialize(encoder, value.value)
    override fun deserialize(decoder: Decoder) = MutableStateFlow(dataSerializer.deserialize(decoder))
}

Mark the specific property to use that serializer:

@Serializeable
class Car {
   @Serializeable(with = MutableStateFlowSerializer::class)
   val speed = MutableStateFlow<Int>(0)
   var isMoving: Boolean = false
}

You need to create a specialized serializer for MutableStateFlow<Int>.

Either based on generic serializer suggested by @Tenfour04

object MutableStateFlowOfIntsSerializer :
    KSerializer<MutableStateFlow<Int>> by MutableStateFlowSerializer(Int.serializer())

class MutableStateFlowSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<MutableStateFlow<T>> {
    override val descriptor: SerialDescriptor = dataSerializer.descriptor
    override fun serialize(encoder: Encoder, value: MutableStateFlow<T>) = dataSerializer.serialize(encoder, value.value)
    override fun deserialize(decoder: Decoder) = MutableStateFlow(dataSerializer.deserialize(decoder))
}

or from scratch:

object MutableStateFlowOfIntsSerializer : KSerializer<MutableStateFlow<Int>> {
    override val descriptor: SerialDescriptor = Int.serializer().descriptor
    override fun serialize(encoder: Encoder, value: MutableStateFlow<Int>) =
        Int.serializer().serialize(encoder, value.value)

    override fun deserialize(decoder: Decoder) = MutableStateFlow(Int.serializer().deserialize(decoder))
}

and wire it to the speed field:

@Serializable
class Car {
    @Serializable(with = MutableStateFlowOfIntsSerializer::class)
    val speed = MutableStateFlow(0)
    var isMoving: Boolean = false
}

Note, that this serialization approach will serialize speed field regardless of encodeDefaults = false setting

Related