Skip to content

Commit c1e314a

Browse files
committed
Introduce JsonTestingMode.EFFICIENT_BINARY as mode that involves a roundtrip
through the EfficientBinaryFormat.
1 parent f27a2e6 commit c1e314a

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonErrorMessagesTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class JsonErrorMessagesTest : JsonTestBase() {
131131
// it can be some kind of path `{"foo:bar:baz":"my:resource:locator:{123}"}` or even URI used as a string key/value.
132132
// So if the closing quote is missing, there's really no way to correctly tell where the key or value is supposed to end.
133133
// Although we may try to unify these messages for consistency.
134-
if (mode in setOf(JsonTestingMode.STREAMING, JsonTestingMode.TREE))
134+
if (mode in setOf(JsonTestingMode.STREAMING, JsonTestingMode.TREE, JsonTestingMode.EFFICIENT_BINARY))
135135
assertContains(
136136
message,
137137
"Unexpected JSON token at offset 7: Expected quotation mark '\"', but had ':' instead at path: \$"
@@ -145,7 +145,7 @@ class JsonErrorMessagesTest : JsonTestBase() {
145145
checkSerializationException({
146146
default.decodeFromString(serString, input2, mode)
147147
}, { message ->
148-
if (mode in setOf(JsonTestingMode.STREAMING, JsonTestingMode.TREE))
148+
if (mode in setOf(JsonTestingMode.STREAMING, JsonTestingMode.TREE, JsonTestingMode.EFFICIENT_BINARY))
149149
assertContains(
150150
message,
151151
"Unexpected JSON token at offset 13: Expected quotation mark '\"', but had '}' instead at path: \$"

formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt

+34-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ enum class JsonTestingMode {
2626
TREE,
2727
OKIO_STREAMS,
2828
JAVA_STREAMS,
29-
KXIO_STREAMS;
29+
KXIO_STREAMS,
30+
EFFICIENT_BINARY;
3031

3132
companion object {
3233
fun value(i: Int) = values()[i]
@@ -42,6 +43,7 @@ abstract class JsonTestBase {
4243
return encodeToString(serializer, value, jsonTestingMode)
4344
}
4445

46+
@OptIn(ExperimentalStdlibApi::class)
4547
internal fun <T> Json.encodeToString(
4648
serializer: SerializationStrategy<T>,
4749
value: T,
@@ -68,13 +70,26 @@ abstract class JsonTestBase {
6870
encodeToSink(serializer, value, buffer)
6971
buffer.readString()
7072
}
73+
JsonTestingMode.EFFICIENT_BINARY -> {
74+
val ebf = EfficientBinaryFormat()
75+
val bytes = runCatching { ebf.encodeToByteArray(serializer, value) }.getOrElse { e->
76+
null//throw e
77+
}
78+
if (bytes != null && serializer is KSerializer<*>) {
79+
val decoded = ebf.decodeFromByteArray((serializer as KSerializer<T>), bytes)
80+
encodeToString(serializer, decoded)
81+
} else {
82+
encodeToString(serializer, value)
83+
}
84+
}
7185
}
7286

7387
internal inline fun <reified T : Any> Json.decodeFromString(source: String, jsonTestingMode: JsonTestingMode): T {
7488
val deserializer = serializersModule.serializer<T>()
7589
return decodeFromString(deserializer, source, jsonTestingMode)
7690
}
7791

92+
@OptIn(ExperimentalStdlibApi::class)
7893
internal fun <T> Json.decodeFromString(
7994
deserializer: DeserializationStrategy<T>,
8095
source: String,
@@ -101,6 +116,20 @@ abstract class JsonTestBase {
101116
buffer.writeString(source)
102117
decodeFromSource(deserializer, buffer)
103118
}
119+
JsonTestingMode.EFFICIENT_BINARY -> {
120+
when (deserializer){
121+
is KSerializer<*> -> {
122+
val s = deserializer as KSerializer<T>
123+
val value = decodeFromString(deserializer, source)
124+
runCatching {
125+
val ebf = EfficientBinaryFormat()
126+
val binaryValue = EfficientBinaryFormat().encodeToByteArray(s, value)
127+
ebf.decodeFromByteArray(s, binaryValue)
128+
}.getOrElse { value }
129+
}
130+
else -> decodeFromString(deserializer, source)
131+
}
132+
}
104133
}
105134

106135
protected open fun parametrizedTest(test: (JsonTestingMode) -> Unit) {
@@ -145,7 +174,10 @@ abstract class JsonTestBase {
145174
@OptIn(ExperimentalStdlibApi::class)
146175
override fun <T> encodeToString(serializer: SerializationStrategy<T>, value: T): String {
147176
bytes = runCatching { ebf.encodeToByteArray(serializer, value) }
148-
.onFailure { if ("Json format" !in it.message!!) throw it }
177+
.onFailure { if ("Json format" !in it.message!!) {
178+
json.encodeToString(serializer, value) // trigger throwing the json exception if the exception is there
179+
throw it
180+
} }
149181
.getOrNull()
150182
return json.encodeToString(serializer, value).also {
151183
if (bytes != null) jsonStr = it

0 commit comments

Comments
 (0)