From ca6d783a1393f12ac6f613cb890f4b421b23cce3 Mon Sep 17 00:00:00 2001 From: Tad Fisher Date: Wed, 13 Mar 2024 18:57:44 -0700 Subject: [PATCH] json: Use @SerialName of inline polymorphic children --- .../SealedInterfacesInlineSerialNameTest.kt | 2 +- .../json/internal/StreamingJsonEncoder.kt | 11 +++++++---- .../json/internal/TreeJsonDecoder.kt | 17 +++++++++++------ .../json/internal/TreeJsonEncoder.kt | 12 +++++++++--- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesInlineSerialNameTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesInlineSerialNameTest.kt index c6f07b12e..c86a5d38d 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesInlineSerialNameTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesInlineSerialNameTest.kt @@ -35,8 +35,8 @@ class SealedInterfacesInlineSerialNameTest : JsonTestBase() { @JvmInline value class Child2(val value: Child2Value) : Parent + // From https://github.com/Kotlin/kotlinx.serialization/issues/2288 @Test - @Ignore // https://github.com/Kotlin/kotlinx.serialization/issues/2288 fun testSealedInterfaceInlineSerialName() { val messages = listOf( Child1(Child1Value(1, "one")), diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt index cf562de5c..dc7b8e7d0 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt @@ -43,6 +43,7 @@ internal class StreamingJsonEncoder( // Forces serializer to wrap all values into quotes private var forceQuoting: Boolean = false private var polymorphicDiscriminator: String? = null + private var polymorphicSerialName: String? = null init { val i = mode.ordinal @@ -66,12 +67,12 @@ internal class StreamingJsonEncoder( } } - private fun encodeTypeInfo(descriptor: SerialDescriptor) { + private fun encodeTypeInfo(discriminator: String, serialName: String) { composer.nextItem() - encodeString(polymorphicDiscriminator!!) + encodeString(discriminator) composer.print(COLON) composer.space() - encodeString(descriptor.serialName) + encodeString(serialName) } override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder { @@ -82,8 +83,9 @@ internal class StreamingJsonEncoder( } if (polymorphicDiscriminator != null) { - encodeTypeInfo(descriptor) + encodeTypeInfo(polymorphicDiscriminator!!, polymorphicSerialName ?: descriptor.serialName) polymorphicDiscriminator = null + polymorphicSerialName = null } if (mode == newMode) { @@ -160,6 +162,7 @@ internal class StreamingJsonEncoder( when { descriptor.isUnsignedNumber -> StreamingJsonEncoder(composerAs(::ComposerForUnsignedNumbers), json, mode, null) descriptor.isUnquotedLiteral -> StreamingJsonEncoder(composerAs(::ComposerForUnquotedLiterals), json, mode, null) + polymorphicDiscriminator != null -> apply { polymorphicSerialName = descriptor.serialName } else -> super.encodeInline(descriptor) } diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt index 690b35e1f..1367e5251 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt @@ -35,7 +35,8 @@ internal fun Json.readPolymorphicJson( private sealed class AbstractJsonTreeDecoder( override val json: Json, - open val value: JsonElement + open val value: JsonElement, + protected val polyDiscriminator: String? = null ) : NamedValueDecoder(), JsonDecoder { override val serializersModule: SerializersModule @@ -63,7 +64,7 @@ private sealed class AbstractJsonTreeDecoder( { JsonTreeMapDecoder(json, cast(currentObject, descriptor)) }, { JsonTreeListDecoder(json, cast(currentObject, descriptor)) } ) - else -> JsonTreeDecoder(json, cast(currentObject, descriptor)) + else -> JsonTreeDecoder(json, cast(currentObject, descriptor), polyDiscriminator) } } @@ -159,11 +160,15 @@ private sealed class AbstractJsonTreeDecoder( override fun decodeInline(descriptor: SerialDescriptor): Decoder { return if (currentTagOrNull != null) super.decodeInline(descriptor) - else JsonPrimitiveDecoder(json, value).decodeInline(descriptor) + else JsonPrimitiveDecoder(json, value, polyDiscriminator).decodeInline(descriptor) } } -private class JsonPrimitiveDecoder(json: Json, override val value: JsonElement) : AbstractJsonTreeDecoder(json, value) { +private class JsonPrimitiveDecoder( + json: Json, + override val value: JsonElement, + polyDiscriminator: String? = null +) : AbstractJsonTreeDecoder(json, value, polyDiscriminator) { init { pushTag(PRIMITIVE_TAG) @@ -180,9 +185,9 @@ private class JsonPrimitiveDecoder(json: Json, override val value: JsonElement) private open class JsonTreeDecoder( json: Json, override val value: JsonObject, - private val polyDiscriminator: String? = null, + polyDiscriminator: String? = null, private val polyDescriptor: SerialDescriptor? = null -) : AbstractJsonTreeDecoder(json, value) { +) : AbstractJsonTreeDecoder(json, value, polyDiscriminator) { private var position = 0 private var forceNull: Boolean = false /* diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt index 5e3c80868..03c1b46cc 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt @@ -35,6 +35,7 @@ private sealed class AbstractJsonTreeEncoder( protected val configuration = json.configuration private var polymorphicDiscriminator: String? = null + private var polymorphicSerialName: String? = null override fun elementName(descriptor: SerialDescriptor, index: Int): String = descriptor.getJsonElementName(json, index) @@ -112,8 +113,12 @@ private sealed class AbstractJsonTreeEncoder( } override fun encodeInline(descriptor: SerialDescriptor): Encoder { - return if (currentTagOrNull != null) super.encodeInline(descriptor) - else JsonPrimitiveEncoder(json, nodeConsumer).encodeInline(descriptor) + return if (currentTagOrNull != null) { + if (polymorphicDiscriminator != null) polymorphicSerialName = descriptor.serialName + super.encodeInline(descriptor) + } else { + JsonPrimitiveEncoder(json, nodeConsumer).encodeInline(descriptor) + } } @SuppressAnimalSniffer // Long(Integer).toUnsignedString(long) @@ -149,8 +154,9 @@ private sealed class AbstractJsonTreeEncoder( } if (polymorphicDiscriminator != null) { - encoder.putElement(polymorphicDiscriminator!!, JsonPrimitive(descriptor.serialName)) + encoder.putElement(polymorphicDiscriminator!!, JsonPrimitive(polymorphicSerialName ?: descriptor.serialName)) polymorphicDiscriminator = null + polymorphicSerialName = null } return encoder