How to create a serializer for a recursive map? Just like `class A : Map<String, A>` . The map...
s
How to create a serializer for a recursive map? Just like
class A : Map<String, A>
. The map is guava multimap that not implement the map interface. But can be converted to a map. Below is what I tried. Will throw
StackOverflowError
from
SetSerializer
Copy code
object Serializer : KSerializer<A> {
    private val serializer by lazy { MapSerializer(String.serializer(), SetSerializer(this)) }
    override val descriptor by lazy {
        SerialDescriptor(
            "A",
            serializer.descriptor
        )
    }
    override fun deserialize(decoder: Decoder) =
        A(Multimaps.newMultimap(serializer.deserialize(decoder)) { setOf() })
    override fun serialize(encoder: Encoder, value: A) =
        serializer.serialize(encoder, value.asMap().mapValues { it.value.toSet() })
}
e
I don't think that's actually what you want to represent a multimap
as
Multimap<K, V> ≅ Map<K, Collection<V>>
that would seem to be a better way to represent it
Copy code
class MultimapSerializer<K, V>(
    keySerializer: KSerializer<K>,
    valueSerializer: KSerializer<V>,
) : KSerializer<Multimap<K, V>> {
    private val surrogateSerializer = MapSerializer(keySerializer, ListSerializer(valueSerializer))
    override val descriptor = SerialDescriptor("com.google.common.collect.Multimap", surrogateSerializer.descriptor)
    override fun serialize(encoder: Encoder, value: Multimap<K, V>) {
        encoder.encodeSerializableValue(surrogateSerializer, value.asMap().mapValues { it.value.toList() })
    }
    override fun deserialize(decoder: Decoder): Multimap<K, V> {
        return Multimaps.newListMultimap(decoder.decodeSerializableValue(surrogateSerializer), ::ArrayList)
    }
}
another representation is that
Multimap<K, V> ≅ Collection<Map.Entry<K, V>>
, so this would be an option as well
Copy code
class MultimapSerializer<K, V>(
    keySerializer: KSerializer<K>,
    valueSerializer: KSerializer<V>,
) : KSerializer<Multimap<K, V>> {
    private val surrogateSerializer = ListSerializer(MapEntrySerializer(keySerializer, valueSerializer))
    override val descriptor = SerialDescriptor("com.google.common.collect.Multimap", surrogateSerializer.descriptor)
    override fun serialize(encoder: Encoder, value: Multimap<K, V>) {
        encoder.encodeSerializableValue(surrogateSerializer, value.entries().toList())
    }
    override fun deserialize(decoder: Decoder): Multimap<K, V> {
        return ImmutableListMultimap.copyOf(decoder.decodeSerializableValue(surrogateSerializer))
    }
}
depending on which representation you prefer
s
What's the different of set and list? The problem is the cyclic dependencies. I've found the
JsonElementSerializer
is using a function named defer for this. But the element descriptor in my case is fetch from a
SetSerializer
, I don't know how to defer that
Edit: It's fine now. With the defer of the descriptor of MapSerializer
140 Views