summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonid Startsev <sandwwraith@users.noreply.github.com>2023-12-04 18:27:42 +0100
committerGitHub <noreply@github.com>2023-12-04 18:27:42 +0100
commitb9945728413253cd5d05141b5e1a26f1130da777 (patch)
tree76229353ca7e7a47af693f0eae5dfad3d7081956
parent7c62a79daa062126f9a12617ca72b4b4c251e204 (diff)
downloadkotlinx.serialization-b9945728413253cd5d05141b5e1a26f1130da777.tar.gz
Make empty objects and arrays collapsed in pretty print mode (#2506)
because it is a widespread convention. Fixes #2502
-rw-r--r--formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonPrettyPrintTest.kt75
-rw-r--r--formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt9
-rw-r--r--formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt2
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)
}
}