Skip to content

Commit 9b82f17

Browse files
authored
Release 1.2.1
Merge pull request #475 from cph-cachet/develop
2 parents 0a465e9 + f4c3994 commit 9b82f17

File tree

15 files changed

+67
-34
lines changed

15 files changed

+67
-34
lines changed

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ buildscript {
33
ext {
44
// Version used for submodule artifacts.
55
// Snapshot publishing changes (or adds) the suffix after '-' with 'SNAPSHOT' prior to publishing.
6-
globalVersion = '1.2.0'
7-
clientsVersion = '1.2.0-alpha.1' // The clients subsystem is still expected to change drastically.
6+
globalVersion = '1.2.1'
7+
clientsVersion = '1.2.1-alpha.1' // The clients subsystem is still expected to change drastically.
88

99
versions = [
1010
// Kotlin multiplatform versions.

carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/reflect/AccessInternals.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package dk.cachet.carp.common.infrastructure.reflect
33

44
/**
55
* Provide access to runtime internals which cannot be accessed at compile time.
6+
*
7+
* Warning: on JavaScript targets, this only works for non-minified sources. Variables which aren't exported are mangled
8+
* completely. So this should not be used in production code! It may still be useful for test automation.
69
*/
710
internal expect object AccessInternals
811
{

carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/serialization/UnknownPolymorphicSerializer.kt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package dk.cachet.carp.common.infrastructure.serialization
22

3-
import dk.cachet.carp.common.infrastructure.reflect.AccessInternals
43
import dk.cachet.carp.common.infrastructure.reflect.reflectIfAvailable
54
import kotlinx.serialization.*
65
import 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
}

carp.test/src/commonMain/kotlin/dk/cachet/carp/test/serialization/ConcreteTypesSerializationTest.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,13 @@ abstract class ConcreteTypesSerializationTest(
4949
for ( toSerialize in instancesToSerialize )
5050
{
5151
// Get serializer.
52+
// Polymorphic serializer is used to ensure type information is always embedded,
53+
// which some deserializers may depend upon.
5254
val type = toSerialize::class
55+
val registration = polymorphicSerializers[ type ]
56+
assertNotNull( registration, "No serializer registered for type '$type'" )
5357
@Suppress( "UNCHECKED_CAST" )
54-
val serializer = polymorphicSerializers[ type ] as? KSerializer<Any>
55-
assertNotNull( serializer, "No serializer registered for type '$type'" )
58+
val serializer = PolymorphicSerializer( registration.baseKlass ) as KSerializer<Any>
5659

5760
// Verify whether serializing and deserializing the instance results in the same object.
5861
val serialized = json.encodeToString( serializer, toSerialize )
@@ -67,12 +70,12 @@ abstract class ConcreteTypesSerializationTest(
6770
* Get a map which holds the [KSerializer] for each [KClass] registered for polymorphic serialization in [serialModule].
6871
*/
6972
@ExperimentalSerializationApi
70-
fun getPolymorphicSerializers( serialModule: SerializersModule ): Map<KClass<*>, KSerializer<*>>
73+
fun getPolymorphicSerializers( serialModule: SerializersModule ): Map<KClass<*>, PolymorphicRegistration>
7174
{
7275
val collector =
7376
object : SerializersModuleCollector
7477
{
75-
val serializers: MutableMap<KClass<*>, KSerializer<*>> = mutableMapOf()
78+
val serializers: MutableMap<KClass<*>, PolymorphicRegistration> = mutableMapOf()
7679

7780
override fun <T : Any> contextual(
7881
kClass: KClass<T>,
@@ -85,7 +88,7 @@ fun getPolymorphicSerializers( serialModule: SerializersModule ): Map<KClass<*>,
8588
actualSerializer: KSerializer<Sub>
8689
)
8790
{
88-
serializers[ actualClass ] = actualSerializer
91+
serializers[ actualClass ] = PolymorphicRegistration( baseClass, actualSerializer )
8992
}
9093

9194
@Suppress( "REDUNDANT_PROJECTION", "KotlinRedundantDiagnosticSuppress" ) // Exact override needed.
@@ -109,3 +112,6 @@ fun getPolymorphicSerializers( serialModule: SerializersModule ): Map<KClass<*>,
109112
serialModule.dumpTo( collector )
110113
return collector.serializers
111114
}
115+
116+
117+
data class PolymorphicRegistration( val baseKlass: KClass<*>, val serializer: KSerializer<*> )

typescript-declarations/carp-common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@cachet/carp-common",
33
"type": "module",
44
"main": "index.js",
5-
"version": "1.1.2"
5+
"version": "1.2.1"
66
}

typescript-declarations/carp-data-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@cachet/carp-data-core",
33
"type": "module",
44
"main": "index.js",
5-
"version": "1.1.2"
5+
"version": "1.2.1"
66
}

typescript-declarations/carp-deployments-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@cachet/carp-deployments-core",
33
"type": "module",
44
"main": "index.js",
5-
"version": "1.1.2"
5+
"version": "1.2.1"
66
}

typescript-declarations/carp-kotlin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@cachet/carp-kotlin",
33
"type": "module",
44
"main": "index.js",
5-
"version": "1.1.2"
5+
"version": "1.2.1"
66
}

typescript-declarations/carp-kotlinx-datetime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"name": "@cachet/carp-kotlinx-datetime",
33
"type": "module",
44
"main": "index.js",
5-
"version": "1.1.2"
5+
"version": "1.2.1"
66
}

typescript-declarations/carp-kotlinx-serialization/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import extendJson from "@cachet/kotlinx-serialization-kotlinx-serialization-json
77
// Facade with better method names and type conversions for internal types.
88
export namespace kotlinx.serialization
99
{
10-
export function getSerializer( type: any ) { return type.Companion.t16() }
10+
export function getSerializer( type: any ) { return type.Companion.m16() }
1111
}
1212
export namespace kotlinx.serialization.json
1313
{

0 commit comments

Comments
 (0)