Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect handling of object end when JsonTreeReader (JsonElement) is used with decodeToSequence #1782

Merged
merged 2 commits into from Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,10 +1,10 @@
/*
* Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* 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

import kotlinx.serialization.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.*

@OptIn(ExperimentalSerializationApi::class)
Expand Down Expand Up @@ -34,8 +34,10 @@ internal class JsonTreeReader(
result[key] = element
// Verify the next token
lastToken = lexer.consumeNextToken()
if (lastToken != TC_COMMA && lastToken != TC_END_OBJ) {
lexer.fail("Expected end of the object or comma")
when (lastToken) {
TC_COMMA -> Unit // no-op, can continue with `canConsumeValue` that verifies the token after comma
TC_END_OBJ -> break // `canConsumeValue` can return incorrect result, since it checks token _after_ TC_END_OBJ
else -> lexer.fail("Expected end of the object or comma")
}
}
// Check for the correct ending
Expand Down
Expand Up @@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.features.sealed.SealedChild
import kotlinx.serialization.features.sealed.SealedParent
import kotlinx.serialization.json.*
import kotlinx.serialization.json.internal.JsonDecodingException
import kotlinx.serialization.test.assertFailsWithMessage
Expand Down Expand Up @@ -108,6 +110,32 @@ class JsonStreamFlowTest {
assertEquals(inputList, json.decodeToSequence(ins, StringData.serializer()).toList())
}

@Test
fun testJsonElement() {
val list = listOf<JsonElement>(
buildJsonObject { put("foo", "bar") },
buildJsonObject { put("foo", "baz") },
JsonPrimitive(10),
JsonPrimitive("abacaba"),
buildJsonObject { put("foo", "qux") }
)
val inputWs = """${list[0]} ${list[1]} ${list[2]} ${list[3]} ${list[4]}"""
val decodedWs = json.decodeToSequence<JsonElement>(inputWs.asInputStream()).toList()
assertEquals(list, decodedWs, "Failed whitespace-separated test")
val inputArray = """[${list[0]}, ${list[1]},${list[2]} , ${list[3]} ,${list[4]}]"""
val decodedArrayWrap = json.decodeToSequence<JsonElement>(inputArray.asInputStream()).toList()
assertEquals(list, decodedArrayWrap, "Failed array-wrapped test")
}


@Test
fun testSealedClasses() {
val input = """{"type":"first child","i":1,"j":10} {"type":"first child","i":1,"j":11}"""
val iter = json.iterateOverStream(input.asInputStream(), SealedParent.serializer())
iter.assertNext(SealedChild(10))
iter.assertNext(SealedChild(11))
}

@Test
fun testMalformedArray() {
val input1 = """[1, 2, 3"""
Expand Down