Skip to content

Commit

Permalink
json: Use @SerialName of inline polymorphic children
Browse files Browse the repository at this point in the history
  • Loading branch information
tadfisher committed Mar 21, 2024
1 parent 63f73f7 commit a3f54a7
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 18 deletions.
Expand Up @@ -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")),
Expand Down
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -81,9 +82,11 @@ internal class StreamingJsonEncoder(
composer.indent()
}

if (polymorphicDiscriminator != null) {
encodeTypeInfo(descriptor)
val discriminator = polymorphicDiscriminator
if (discriminator != null) {
encodeTypeInfo(discriminator, polymorphicSerialName ?: descriptor.serialName)
polymorphicDiscriminator = null
polymorphicSerialName = null
}

if (mode == newMode) {
Expand Down Expand Up @@ -160,6 +163,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)
}

Expand Down
Expand Up @@ -35,7 +35,8 @@ internal fun <T> Json.readPolymorphicJson(

private sealed class AbstractJsonTreeDecoder(
override val json: Json,
open val value: JsonElement
open val value: JsonElement,
protected val polymorphicDiscriminator: String? = null
) : NamedValueDecoder(), JsonDecoder {

override val serializersModule: SerializersModule
Expand Down Expand Up @@ -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), polymorphicDiscriminator)
}
}

Expand Down Expand Up @@ -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, polymorphicDiscriminator).decodeInline(descriptor)
}
}

private class JsonPrimitiveDecoder(json: Json, override val value: JsonElement) : AbstractJsonTreeDecoder(json, value) {
private class JsonPrimitiveDecoder(
json: Json,
override val value: JsonElement,
polymorphicDiscriminator: String? = null
) : AbstractJsonTreeDecoder(json, value, polymorphicDiscriminator) {

init {
pushTag(PRIMITIVE_TAG)
Expand All @@ -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,
polymorphicDiscriminator: String? = null,
private val polyDescriptor: SerialDescriptor? = null
) : AbstractJsonTreeDecoder(json, value) {
) : AbstractJsonTreeDecoder(json, value, polymorphicDiscriminator) {
private var position = 0
private var forceNull: Boolean = false
/*
Expand Down Expand Up @@ -251,7 +256,7 @@ private open class JsonTreeDecoder(
// in endStructure can filter polyDiscriminator out.
if (descriptor === polyDescriptor) {
return JsonTreeDecoder(
json, cast(currentObject(), polyDescriptor), polyDiscriminator, polyDescriptor
json, cast(currentObject(), polyDescriptor), polymorphicDiscriminator, polyDescriptor
)
}

Expand All @@ -271,7 +276,7 @@ private open class JsonTreeDecoder(
}

for (key in value.keys) {
if (key !in names && key != polyDiscriminator) {
if (key !in names && key != polymorphicDiscriminator) {
throw UnknownKeyException(key, value.toString())
}
}
Expand Down
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -148,9 +153,11 @@ private sealed class AbstractJsonTreeEncoder(
else -> JsonTreeEncoder(json, consumer)
}

if (polymorphicDiscriminator != null) {
encoder.putElement(polymorphicDiscriminator!!, JsonPrimitive(descriptor.serialName))
val discriminator = polymorphicDiscriminator
if (discriminator != null) {
encoder.putElement(discriminator, JsonPrimitive(polymorphicSerialName ?: descriptor.serialName))
polymorphicDiscriminator = null
polymorphicSerialName = null
}

return encoder
Expand Down

0 comments on commit a3f54a7

Please sign in to comment.