diff options
Diffstat (limited to 'formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt')
-rw-r--r-- | formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt | 44 |
1 files changed, 29 insertions, 15 deletions
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) { |