summaryrefslogtreecommitdiff
path: root/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt
diff options
context:
space:
mode:
Diffstat (limited to 'formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt')
-rw-r--r--formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt41
1 files changed, 24 insertions, 17 deletions
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 cdaeeb03..cf562de5 100644
--- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt
+++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.serialization.json.internal
@@ -10,11 +10,7 @@ import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
-import kotlin.native.concurrent.*
-@ExperimentalSerializationApi
-@OptIn(ExperimentalUnsignedTypes::class)
-@SharedImmutable
private val unsignedNumberDescriptors = setOf(
UInt.serializer().descriptor,
ULong.serializer().descriptor,
@@ -22,11 +18,13 @@ private val unsignedNumberDescriptors = setOf(
UShort.serializer().descriptor
)
-@ExperimentalSerializationApi
internal val SerialDescriptor.isUnsignedNumber: Boolean
get() = this.isInline && this in unsignedNumberDescriptors
-@OptIn(ExperimentalSerializationApi::class, ExperimentalUnsignedTypes::class)
+internal val SerialDescriptor.isUnquotedLiteral: Boolean
+ get() = this.isInline && this == jsonUnquotedLiteralDescriptor
+
+@OptIn(ExperimentalSerializationApi::class)
internal class StreamingJsonEncoder(
private val composer: Composer,
override val json: Json,
@@ -35,7 +33,7 @@ internal class StreamingJsonEncoder(
) : JsonEncoder, AbstractEncoder() {
internal constructor(
- output: JsonStringBuilder, json: Json, mode: WriteMode,
+ output: InternalJsonWriter, json: Json, mode: WriteMode,
modeReuseCache: Array<JsonEncoder?>
) : this(Composer(output, json), json, mode, modeReuseCache)
@@ -98,7 +96,7 @@ internal class StreamingJsonEncoder(
override fun endStructure(descriptor: SerialDescriptor) {
if (mode.end != INVALID) {
composer.unIndent()
- composer.nextItem()
+ composer.nextItemIfNotFirst()
composer.print(mode.end)
}
}
@@ -139,7 +137,7 @@ internal class StreamingJsonEncoder(
if (!composer.writingFirst)
composer.print(COMMA)
composer.nextItem()
- encodeString(descriptor.getElementName(index))
+ encodeString(descriptor.getJsonElementName(json, index))
composer.print(COLON)
composer.space()
}
@@ -158,11 +156,20 @@ internal class StreamingJsonEncoder(
}
}
- override fun encodeInline(inlineDescriptor: SerialDescriptor): Encoder =
- if (inlineDescriptor.isUnsignedNumber) StreamingJsonEncoder(
- ComposerForUnsignedNumbers(composer.sb), json, mode, null
- )
- else super.encodeInline(inlineDescriptor)
+ override fun encodeInline(descriptor: SerialDescriptor): Encoder =
+ when {
+ descriptor.isUnsignedNumber -> StreamingJsonEncoder(composerAs(::ComposerForUnsignedNumbers), json, mode, null)
+ descriptor.isUnquotedLiteral -> StreamingJsonEncoder(composerAs(::ComposerForUnquotedLiterals), json, mode, null)
+ else -> super.encodeInline(descriptor)
+ }
+
+ private inline fun <reified T: Composer> composerAs(composerCreator: (writer: InternalJsonWriter, forceQuoting: Boolean) -> T): T {
+ // If we're inside encodeInline().encodeSerializableValue, we should preserve the forceQuoting state
+ // inside the composer, but not in the encoder (otherwise we'll get into `if (forceQuoting) encodeString(value.toString())` part
+ // and unsigned numbers would be encoded incorrectly)
+ return if (composer is T) composer
+ else composerCreator(composer.writer, forceQuoting)
+ }
override fun encodeNull() {
composer.print(NULL)
@@ -192,7 +199,7 @@ internal class StreamingJsonEncoder(
// First encode value, then check, to have a prettier error message
if (forceQuoting) encodeString(value.toString()) else composer.print(value)
if (!configuration.allowSpecialFloatingPointValues && !value.isFinite()) {
- throw InvalidFloatingPointEncoded(value, composer.sb.toString())
+ throw InvalidFloatingPointEncoded(value, composer.writer.toString())
}
}
@@ -200,7 +207,7 @@ internal class StreamingJsonEncoder(
// First encode value, then check, to have a prettier error message
if (forceQuoting) encodeString(value.toString()) else composer.print(value)
if (!configuration.allowSpecialFloatingPointValues && !value.isFinite()) {
- throw InvalidFloatingPointEncoded(value, composer.sb.toString())
+ throw InvalidFloatingPointEncoded(value, composer.writer.toString())
}
}