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

Polymorphic primitive collection serialization.

Open csbence opened this issue 8 years ago • 4 comments

When serializing a polymorphic collation of primitives using the PolymorphicSerializer the type is always included. Including the type of the primitives might not be necessary. I feel like this is a common use case thus it should be addressed.

Example

val list = listOf(1, 2.0, "a")
val json = JSON.stringify(PolymorphicSerializer.list, list)
println(json) 
// [["kotlin.Int",1],["kotlin.Double",2.0],["kotlin.String","a"]]
// jackson would output the following: [1, 2.0, "a"]

Possible solutions

  1. PolymorphicSerializer::save could omit the type information when serializing primitives or standard collections.
  2. Configurable PolymorphicSerializer class or a different object that behaves as described above. It might be desired to fine tune such behavior.

csbence avatar Dec 01 '17 07:12 csbence

The root of the problem is that PolymorphicSerializer was created in a such way that objects written by him are intended to be easily restored in statically typed language. So, efficiently, here you are writing a List<Any>. If you try deserialize it back, parser will fail even with primitives: there's no way to properly create Any from String (except for just coercing it); moreover, parser doesn't know, if he supposed to read string or int or double now. Indeed, right type could be inferenced from parsed string, but it will make parser more complex and probably slower.

So my suggestion is to create something that could be probably called ToDynamicSerializer, which is intended to write strings that can be easily consumed by parsers which don't need full type info (e.g. JavaScript). It can omit types either for primitives or for all objects, or may be tunable - this should be designed. If you have some use cases for it, please feel free to post it here.

sandwwraith avatar Dec 06 '17 09:12 sandwwraith

My use case is the following. I have dynamic data store, that has fixed elements with a type and dynamic fields where the type might be unknown.

class MixedDataStore(private val valueStore: MutableMap<String, Any?> = hashMapOf()) {
    var foo: String by valueStore
    var bar: Long by valueStore

    operator fun get(key: String): Any? = valueStore[key]
    fun <T> getTypedValue(key: String): T? = this[key] as? T
    fun contains(key: String) = valueStore.containsKey(key)
}

csbence avatar Dec 28 '17 22:12 csbence

Note that omitting the wrapping and explicit typing could be omitted by the encoder/decoder. Obviously they then need an alternative way to indicate the type of the object encoded/decoded.

pdvrieze avatar Sep 20 '18 18:09 pdvrieze

Hey, I stumbled upon this while trying to figure out how to register primitives and nulls. I made a stack overflow question about this exact problem here: https://stackoverflow.com/questions/72325605/how-to-properly-register-primitives-and-nulls-in-polymorphic-serialization

mgroth0 avatar May 20 '22 23:05 mgroth0