kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

Mixed map CBOR serialization is failing

Open yackermann opened this issue 5 years ago • 2 comments

Describe the bug When trying to serialize map with values set to different it throws an error: kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.

To Reproduce Attach a code snippet or test data if possible.


fun testCBOR() {

    val goodMap =  mapOf(
           1 to 2,
           3 to -7,
           -1 to 1
    )

    val badMapIntMixedWithString = mapOf(
           1 to 2,
           3 to -7,
           -1 to 1,
           -4 to "hello"
    )

    val badMapIntMixedWithBytes = mapOf(
           1 to 2,
           3 to -7,
           -1 to 1,
           -5 to byteArrayOf(1,2,3,4,5,6,7,8)
    )



    Cbor.encodeToByteArray(goodMap)
    Cbor.encodeToByteArray(badMapIntMixedWithString)
    Cbor.encodeToByteArray(badMapIntMixedWithBytes)
}

Full stack

 kotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
    Mark the class as @Serializable or provide the serializer explicitly.
        at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
        at kotlinx.serialization.internal.PlatformKt.platformSpecificSerializerNotRegistered(Platform.kt:29)
        at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:59)
        at kotlinx.serialization.SerializersKt.serializer(Unknown Source:1)
        at kotlinx.serialization.SerializersKt__SerializersKt.builtinSerializerOrNull$SerializersKt__SerializersKt(Serializers.kt:79)
        at kotlinx.serialization.SerializersKt__SerializersKt.serializerByKTypeImpl$SerializersKt__SerializersKt(Serializers.kt:69)
        at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:54)
        at kotlinx.serialization.SerializersKt.serializer(Unknown Source:1)
        at uaf.playground.PlaygroundKt.testCBOR(Playground.kt:46)

Expected behavior Serialized output

Environment

  • Kotlin version: [e.g. 1.4.10]
  • Library version: [e.g. 1.0.1]
  • Kotlin platforms: [e.g. JVM, Native, Kotlin]
  • Gradle version: [e.g. 4.10]
  • IDE version (if bug is related to the IDE) [Android Studio 4.1]

yackermann avatar Dec 10 '20 02:12 yackermann

That's because the static type of your map is Map<String, Any>. kotlinx.serialization does not support Any polymorphism out of the box because it may be unpredictable in many ways. I'd recommend to use Map<String, String>. If you still need to use Any, pass MapSerializer(String.serializer(), PolymorphicSerializer(Any::class)) to encodeToByteArray and consult documentation on how to register all the types that you need.

sandwwraith avatar Dec 11 '20 14:12 sandwwraith

@sandwwraith Might be good idea to write a doc on it. There are a lot of Identity where mixed type maps are used. My current pain point is that I actually need a map, because I need an integer keys, but values are mixed. Classes working just fine

yackermann avatar Dec 11 '20 19:12 yackermann