Skip to content

Commit

Permalink
Quote integer-like map keys in JsonPath to properly distinguish them …
Browse files Browse the repository at this point in the history
…from array indicies
  • Loading branch information
qwwdfsad committed Mar 21, 2022
1 parent 85dce74 commit 358e1a5
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
Expand Up @@ -2,6 +2,7 @@ package kotlinx.serialization.json.internal

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.internal.*

/**
* Internal representation of the current JSON path.
Expand All @@ -20,6 +21,9 @@ import kotlinx.serialization.descriptors.*
* ```
*/
internal class JsonPath {

// Tombstone indicates that we are within a map, but the map key is currently being decoded.
// It is also used to overwrite a previous map key to avoid memory leaks and misattribution.
object Tombstone

/*
Expand Down Expand Up @@ -68,6 +72,7 @@ internal class JsonPath {
indicies[currentDepth] = -2
}

/** Used to indicate that we are in the process of decoding the key itself and can't specify it in path */
fun resetCurrentMapKey() {
if (indicies[currentDepth] == -2) {
currentObjectPath[currentDepth] = Tombstone
Expand Down Expand Up @@ -111,8 +116,13 @@ internal class JsonPath {
}
} else if (element !== Tombstone) {
append("[")
// Else -- structured key
// With this check numbers keys will be quoted,
// so both [42] and ['42'] are now non ambiguous
val isNumberKey = element is Number
if (isNumberKey) append("'")
// Else -- map key
append(element)
if (isNumberKey) append("'")
append("]")
}
}
Expand Down
Expand Up @@ -29,7 +29,7 @@ class JsonPathTest : JsonTestBase() {

@Test
fun testMissingKey() {
expectPath("$.i.d[1]") { Json.decodeFromString<Outer>("""{"a":42, "i":{"d":{1:{}}""") }
expectPath("$.i.d['1']") { Json.decodeFromString<Outer>("""{"a":42, "i":{"d":{1:{}}""") }
}

@Test
Expand Down Expand Up @@ -76,9 +76,9 @@ class JsonPathTest : JsonTestBase() {

@Test
fun testMapValue() {
expectPath("$.i.d[42]\n") { Json.decodeFromString<Outer>("""{"a":42, "i":{ "d": {42: {"xx":"bar"}}""") }
expectPath("$.i.d[43]\n") { Json.decodeFromString<Outer>("""{"a":42, "i":{ "d": {42: {"s":"s"}, 43: {"xx":"bar"}}}""") }
expectPath("$[239]") { Json.decodeFromString<Map<Int, String>>("""{239:bar}""") }
expectPath("$.i.d['42']\n") { Json.decodeFromString<Outer>("""{"a":42, "i":{ "d": {42: {"xx":"bar"}}""") }
expectPath("$.i.d['43']\n") { Json.decodeFromString<Outer>("""{"a":42, "i":{ "d": {42: {"s":"s"}, 43: {"xx":"bar"}}}""") }
expectPath("$['239']") { Json.decodeFromString<Map<Int, String>>("""{239:bar}""") }
}

@Serializable
Expand Down

0 comments on commit 358e1a5

Please sign in to comment.