11package dk.cachet.carp.common.infrastructure.serialization
22
3- import dk.cachet.carp.common.infrastructure.reflect.AccessInternals
43import dk.cachet.carp.common.infrastructure.reflect.reflectIfAvailable
54import kotlinx.serialization.*
65import kotlinx.serialization.descriptors.*
@@ -58,18 +57,30 @@ abstract class UnknownPolymorphicSerializer<P : Any, W : P>(
5857 {
5958 throw unsupportedException
6059 }
61- getClassDiscriminator( encoder.json ) // Throws error in case array polymorphism is used .
60+ val classDiscriminator = getClassDiscriminator( encoder.json ) // Throws error in case of array polymorphism.
6261
6362 // Get the unknown JSON object.
6463 check( value is UnknownPolymorphicWrapper )
6564 val unknown = Json .parseToJsonElement( value.jsonSource ) as JsonObject
65+ val unknownTypeFields = unknown.filter { it.key != classDiscriminator }
66+
67+ // Create a serial descriptor which contains all elements of the unknown JSON object, except type discriminator.
68+ // If the encoder is in polymorphic writing mode, a class discriminator field will automatically be added using
69+ // the serial name of the descriptor.
70+ val unknownType = checkNotNull( unknown[ classDiscriminator ]?.jsonPrimitive?.content )
71+ val jsonSerializer = JsonElement .serializer()
72+ val overrideDescriptor = buildClassSerialDescriptor( unknownType )
73+ {
74+ unknownTypeFields.keys.forEach { element( it, jsonSerializer.descriptor ) }
75+ }
6676
67- // HACK: Modify kotlinx.serialization internals to ensure the encoder is not in polymorphic mode.
68- // Otherwise, `encoder.encodeJsonElement` encodes type information, but this is already represented in the wrapped unknown object.
69- AccessInternals .setField( encoder, " polymorphicDiscriminator" , null )
70-
71- // Output the originally wrapped JSON.
72- encoder.encodeJsonElement( unknown )
77+ // Write the JSON object.
78+ encoder.encodeStructure( overrideDescriptor )
79+ {
80+ var id = 0
81+ for ( field in unknownTypeFields.values )
82+ encodeSerializableElement( overrideDescriptor, id++ , JsonElement .serializer(), field )
83+ }
7384 }
7485
7586 override fun deserialize ( decoder : Decoder ): P
@@ -85,7 +96,8 @@ abstract class UnknownPolymorphicSerializer<P : Any, W : P>(
8596 // Get raw JSON for the unknown type.
8697 val jsonElement = decoder.decodeJsonElement()
8798 val jsonSource = jsonElement.toString()
88- val className = jsonElement.jsonObject[ classDiscriminator ]!! .jsonPrimitive.content
99+ val className = requireNotNull( jsonElement.jsonObject[ classDiscriminator ]?.jsonPrimitive?.content )
100+ { " Can't deserialize type which was serialized non-polymorphically." }
89101
90102 return createWrapper( className, jsonSource, decoder.json )
91103 }
0 commit comments