diff options
Diffstat (limited to 'formats/json/jsMain/src/kotlinx')
5 files changed, 31 insertions, 67 deletions
diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/JsonSchemaCache.kt b/formats/json/jsMain/src/kotlinx/serialization/json/JsonSchemaCache.kt deleted file mode 100644 index a0820ef4..00000000 --- a/formats/json/jsMain/src/kotlinx/serialization/json/JsonSchemaCache.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.serialization.json - -import kotlinx.serialization.json.internal.* - -@Suppress("DEPRECATION_ERROR") -internal actual val Json.schemaCache: DescriptorSchemaCache get() = this._schemaCache diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt index a6658c7c..1ff1e40d 100644 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt +++ b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt @@ -73,7 +73,7 @@ private open class DynamicInput( private fun coerceInputValue(descriptor: SerialDescriptor, index: Int, tag: String): Boolean = json.tryCoerceValue( - descriptor.getElementDescriptor(index), + descriptor, index, { getByTag(tag) == null }, { getByTag(tag) as? String } ) @@ -100,18 +100,27 @@ private open class DynamicInput( return forceNull } - override fun elementName(desc: SerialDescriptor, index: Int): String { - val mainName = desc.getElementName(index) - if (!json.configuration.useAlternativeNames) return mainName - // Fast path, do not go through Map.get - // Note, it blocks ability to detect collisions between the primary name and alternate, - // but it eliminates a significant performance penalty (about -15% without this optimization) - if (hasName(mainName)) return mainName + override fun elementName(descriptor: SerialDescriptor, index: Int): String { + val strategy = descriptor.namingStrategy(json) + val mainName = descriptor.getElementName(index) + if (strategy == null) { + if (!json.configuration.useAlternativeNames) return mainName + // Fast path, do not go through Map.get + // Note, it blocks ability to detect collisions between the primary name and alternate, + // but it eliminates a significant performance penalty (about -15% without this optimization) + if (hasName(mainName)) return mainName + } // Slow path - val alternativeNamesMap = - json.schemaCache.getOrPut(desc, JsonAlternativeNamesKey, desc::buildAlternativeNamesMap) - val nameInObject = (keys as Array<String>).find { alternativeNamesMap[it] == index } - return nameInObject ?: mainName + val deserializationNamesMap = json.deserializationNamesMap(descriptor) + (keys as Array<String>).find { deserializationNamesMap[it] == index }?.let { + return it + } + val fallbackName = strategy?.serialNameForJson( + descriptor, + index, + mainName + ) // Key not found exception should be thrown with transformed name, not original + return fallbackName ?: mainName } override fun decodeTaggedEnum(tag: String, enumDescriptor: SerialDescriptor): Int { @@ -125,7 +134,12 @@ private open class DynamicInput( override fun decodeTaggedChar(tag: String): Char { return when (val value = getByTag(tag)) { is String -> if (value.length == 1) value[0] else throw SerializationException("$value can't be represented as Char") - is Number -> value.toChar() + is Number -> { + val num = value as? Double ?: throw SerializationException("$value is not a Number") + val codePoint = toJavascriptLong(num) + if (codePoint < 0 || codePoint > Char.MAX_VALUE.code) throw SerializationException("$value can't be represented as Char because it's not in bounds of Char.MIN_VALUE..Char.MAX_VALUE") + codePoint.toInt().toChar() + } else -> throw SerializationException("$value can't be represented as Char") } } @@ -191,7 +205,7 @@ private class DynamicMapInput( private var currentPosition = -1 private val isKey: Boolean get() = currentPosition % 2 == 0 - override fun elementName(desc: SerialDescriptor, index: Int): String { + override fun elementName(descriptor: SerialDescriptor, index: Int): String { val i = index / 2 return keys[i] as String } @@ -261,7 +275,7 @@ private class DynamicListInput( override val size = value.length as Int private var currentPosition = -1 - override fun elementName(desc: SerialDescriptor, index: Int): String = (index).toString() + override fun elementName(descriptor: SerialDescriptor, index: Int): String = (index).toString() override fun decodeElementIndex(descriptor: SerialDescriptor): Int { while (currentPosition < size - 1) { diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicEncoders.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicEncoders.kt index 4bd46d59..4c4841d4 100644 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicEncoders.kt +++ b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicEncoders.kt @@ -81,7 +81,7 @@ private class DynamicObjectEncoder( when { current.writeMode == WriteMode.MAP -> currentElementIsMapKey = current.index % 2 == 0 current.writeMode == WriteMode.LIST && descriptor.kind is PolymorphicKind -> currentName = index.toString() - else -> currentName = descriptor.getElementName(index) + else -> currentName = descriptor.getJsonElementName(json, index) } return true @@ -257,7 +257,7 @@ private class DynamicPrimitiveEncoder( if (!json.configuration.isLenient && abs(value) > MAX_SAFE_INTEGER) { throw IllegalArgumentException( "$value can't be deserialized to number due to a potential precision loss. " + - "Use the JsonConfiguration option isLenient to serialise anyway" + "Use the JsonConfiguration option isLenient to serialize anyway" ) } encodeValue(asDouble) diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt deleted file mode 100644 index 1b79e27e..00000000 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt +++ /dev/null @@ -1,28 +0,0 @@ -package kotlinx.serialization.json.internal - -internal actual class JsonStringBuilder actual constructor() { - private val sb = StringBuilder(128) - - actual fun append(value: Long) { - sb.append(value) - } - - actual fun append(ch: Char) { - sb.append(ch) - } - - actual fun append(string: String) { - sb.append(string) - } - - actual fun appendQuoted(string: String) { - sb.printQuoted(string) - } - - actual override fun toString(): String { - return sb.toString() - } - - actual fun release() { - } -} diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/createMapForCache.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/createMapForCache.kt deleted file mode 100644 index b51ff401..00000000 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/createMapForCache.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.serialization.json.internal - -/** - * Creates a ConcurrentHashMap on JVM and regular HashMap on other platforms. - * To make actual use of cache in Kotlin/Native, mark a top-level object with this map - * as a @[ThreadLocal]. - */ -internal actual fun <K, V> createMapForCache(initialCapacity: Int): MutableMap<K, V> = HashMap(initialCapacity) |