Skip to content

Commit

Permalink
Make empty objects and arrays collapsed in pretty print mode (#2506)
Browse files Browse the repository at this point in the history
because it is a widespread convention.

Fixes #2502
  • Loading branch information
sandwwraith authored Dec 4, 2023
1 parent 7c62a79 commit b994572
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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(' ')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down

0 comments on commit b994572

Please sign in to comment.