diff options
author | Leonid Startsev <sandwwraith@users.noreply.github.com> | 2023-12-04 18:27:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-04 18:27:42 +0100 |
commit | b9945728413253cd5d05141b5e1a26f1130da777 (patch) | |
tree | 76229353ca7e7a47af693f0eae5dfad3d7081956 | |
parent | 7c62a79daa062126f9a12617ca72b4b4c251e204 (diff) | |
download | kotlinx.serialization-b9945728413253cd5d05141b5e1a26f1130da777.tar.gz |
Make empty objects and arrays collapsed in pretty print mode (#2506)
because it is a widespread convention.
Fixes #2502
3 files changed, 85 insertions, 1 deletions
diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonPrettyPrintTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonPrettyPrintTest.kt new file mode 100644 index 00000000..8283e25b --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonPrettyPrintTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json + +import kotlinx.serialization.* +import kotlin.test.* + +class JsonPrettyPrintTest : JsonTestBase() { + val fmt = Json(default) { prettyPrint = true; encodeDefaults = true } + + @Serializable + class Empty + + @Serializable + class A(val empty: Empty = Empty()) + + @Serializable + class B(val prefix: String = "a", val empty: Empty = Empty(), val postfix: String = "b") + + @Serializable + class Recursive(val rec: Recursive?, val empty: Empty = Empty()) + + @Serializable + class WithListRec(val rec: WithListRec?, val l: List<Int> = listOf()) + + @Serializable + class WithDefaults(val x: String = "x", val y: Int = 0) + + @Test + fun testTopLevel() = parametrizedTest { mode -> + assertEquals("{}", fmt.encodeToString(Empty(), mode)) + } + + @Test + fun testWithDefaults() = parametrizedTest { mode -> + val dropDefaults = Json(fmt) { encodeDefaults = false } + val s = "{\n \"boxed\": {}\n}" + assertEquals(s, dropDefaults.encodeToString(Box(WithDefaults()), mode)) + } + + @Test + fun testPlain() = parametrizedTest { mode -> + val s = """{ + | "empty": {} + |}""".trimMargin() + assertEquals(s, fmt.encodeToString(A(), mode)) + } + + @Test + fun testInside() = parametrizedTest { mode -> + val s = """{ + | "prefix": "a", + | "empty": {}, + | "postfix": "b" + |}""".trimMargin() + assertEquals(s, fmt.encodeToString(B(), mode)) + } + + @Test + fun testRecursive() = parametrizedTest { mode -> + val obj = Recursive(Recursive(null)) + val s = "{\n \"rec\": {\n \"rec\": null,\n \"empty\": {}\n },\n \"empty\": {}\n}" + assertEquals(s, fmt.encodeToString(obj, mode)) + } + + @Test + fun test() = parametrizedTest { mode -> + val obj = WithListRec(WithListRec(null), listOf(1, 2, 3)) + val s = + "{\n \"rec\": {\n \"rec\": null,\n \"l\": []\n },\n \"l\": [\n 1,\n 2,\n 3\n ]\n}" + assertEquals(s, fmt.encodeToString(obj, mode)) + } +} diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt index c1ed8cca..abdd1c44 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt @@ -27,6 +27,10 @@ internal open class Composer(@JvmField internal val writer: InternalJsonWriter) writingFirst = false } + open fun nextItemIfNotFirst() { + writingFirst = false + } + open fun space() = Unit fun print(v: Char) = writer.writeChar(v) @@ -88,6 +92,11 @@ internal class ComposerWithPrettyPrint( repeat(level) { print(json.configuration.prettyPrintIndent) } } + override fun nextItemIfNotFirst() { + if (writingFirst) writingFirst = false + else nextItem() + } + override fun space() { print(' ') } diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt index 4f7b1ec7..cf562de5 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt @@ -96,7 +96,7 @@ internal class StreamingJsonEncoder( override fun endStructure(descriptor: SerialDescriptor) { if (mode.end != INVALID) { composer.unIndent() - composer.nextItem() + composer.nextItemIfNotFirst() composer.print(mode.end) } } |