summaryrefslogtreecommitdiff
path: root/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt
diff options
context:
space:
mode:
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.kt44
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) {