diff --git a/benchmark/build.gradle b/benchmark/build.gradle index 0935e5a35..827726bf4 100644 --- a/benchmark/build.gradle +++ b/benchmark/build.gradle @@ -13,19 +13,26 @@ sourceCompatibility = 1.8 targetCompatibility = 1.8 jmh.jmhVersion = "1.22" +processJmhResources { + doFirst { + duplicatesStrategy(DuplicatesStrategy.EXCLUDE) + } +} + jmhJar { - baseName 'benchmarks' - classifier = null - version = null - destinationDir = file("$rootDir") + archiveBaseName.set('benchmarks') + archiveVersion.set('') + destinationDirectory = file("$rootDir") } dependencies { implementation 'org.openjdk.jmh:jmh-core:1.22' - implementation 'com.google.guava:guava:24.1.1-jre' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.1' - implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.12.1' + implementation 'com.google.guava:guava:31.1-jre' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3' + implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3' + implementation "com.squareup.okio:okio:$okio_version" implementation project(':kotlinx-serialization-core') implementation project(':kotlinx-serialization-json') + implementation project(':kotlinx-serialization-json-okio') implementation project(':kotlinx-serialization-protobuf') } diff --git a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt index b81250014..783888b4e 100644 --- a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt +++ b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/JacksonComparisonBenchmark.kt @@ -4,7 +4,11 @@ import com.fasterxml.jackson.databind.* import com.fasterxml.jackson.module.kotlin.* import kotlinx.serialization.* import kotlinx.serialization.json.* +import kotlinx.serialization.json.okio.encodeToSink +import okio.blackholeSink +import okio.buffer import org.openjdk.jmh.annotations.* +import java.io.OutputStream import java.util.concurrent.* @Warmup(iterations = 7, time = 1) @@ -63,6 +67,13 @@ open class JacksonComparisonBenchmark { cookies = "_ga=GA1.2.971852807.1546968515" ) + private val devNullSink = blackholeSink().buffer() + private val devNullStream = object : OutputStream() { + override fun write(b: Int) {} + override fun write(b: ByteArray) {} + override fun write(b: ByteArray, off: Int, len: Int) {} + } + private val stringData = Json.encodeToString(DefaultPixelEvent.serializer(), data) @Serializable @@ -82,12 +93,24 @@ open class JacksonComparisonBenchmark { @Benchmark fun kotlinToString(): String = Json.encodeToString(DefaultPixelEvent.serializer(), data) + @Benchmark + fun kotlinToStream() = Json.encodeToStream(DefaultPixelEvent.serializer(), data, devNullStream) + + @Benchmark + fun kotlinToOkio() = Json.encodeToSink(DefaultPixelEvent.serializer(), data, devNullSink) + @Benchmark fun kotlinToStringWithEscapes(): String = Json.encodeToString(DefaultPixelEvent.serializer(), dataWithEscapes) @Benchmark fun kotlinSmallToString(): String = Json.encodeToString(SmallDataClass.serializer(), smallData) + @Benchmark + fun kotlinSmallToStream() = Json.encodeToStream(SmallDataClass.serializer(), smallData, devNullStream) + + @Benchmark + fun kotlinSmallToOkio() = Json.encodeToSink(SmallDataClass.serializer(), smallData, devNullSink) + @Benchmark fun jacksonFromString(): DefaultPixelEvent = objectMapper.readValue(stringData, DefaultPixelEvent::class.java) diff --git a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/TwitterBenchmark.kt b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/TwitterBenchmark.kt index 5c930ec6a..90889fe85 100644 --- a/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/TwitterBenchmark.kt +++ b/benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/TwitterBenchmark.kt @@ -3,6 +3,7 @@ package kotlinx.benchmarks.json import kotlinx.benchmarks.model.* import kotlinx.serialization.json.* import org.openjdk.jmh.annotations.* +import java.io.OutputStream import java.util.concurrent.* @Warmup(iterations = 7, time = 1) @@ -24,6 +25,12 @@ open class TwitterBenchmark { private val jsonImplicitNulls = Json { explicitNulls = false } + private val devNullStream = object : OutputStream() { + override fun write(b: Int) {} + override fun write(b: ByteArray) {} + override fun write(b: ByteArray, off: Int, len: Int) {} + } + @Setup fun init() { require(twitter == Json.decodeFromString(Twitter.serializer(), Json.encodeToString(Twitter.serializer(), twitter))) @@ -38,4 +45,7 @@ open class TwitterBenchmark { @Benchmark fun encodeTwitter() = Json.encodeToString(Twitter.serializer(), twitter) + + @Benchmark + fun encodeTwitterStream() = Json.encodeToStream(Twitter.serializer(), twitter, devNullStream) } diff --git a/build.gradle b/build.gradle index f696639fc..15dd39795 100644 --- a/build.gradle +++ b/build.gradle @@ -144,6 +144,8 @@ allprojects { } } +def unpublishedProjects = ["benchmark", "guide", "kotlinx-serialization-json-tests"] as Set + subprojects { tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all { task -> if (task.name.contains("Test") || task.name.contains("Jmh")) { @@ -155,7 +157,7 @@ subprojects { apply from: rootProject.file('gradle/teamcity.gradle') // Configure publishing for some artifacts - if (project.name != "benchmark" && project.name != "guide") { + if (!unpublishedProjects.contains(project.name)) { apply from: rootProject.file('gradle/publishing.gradle') } diff --git a/formats/json-okio/api/kotlinx-serialization-json-okio.api b/formats/json-okio/api/kotlinx-serialization-json-okio.api new file mode 100644 index 000000000..4b3f0a2c3 --- /dev/null +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -0,0 +1,7 @@ +public final class kotlinx/serialization/json/okio/OkioStreamsKt { + public static final fun decodeFromSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/Source;)Ljava/lang/Object; + public static final fun decodeSourceToSequence (Lkotlinx/serialization/json/Json;Lokio/Source;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeSourceToSequence$default (Lkotlinx/serialization/json/Json;Lokio/Source;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; + public static final fun encodeToSink (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/Sink;)V +} + diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts new file mode 100644 index 000000000..3e6565e9e --- /dev/null +++ b/formats/json-okio/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +import Java9Modularity.configureJava9ModuleInfo + +plugins { + kotlin("multiplatform") + kotlin("plugin.serialization") +} + +apply(from = rootProject.file("gradle/native-targets.gradle")) +apply(from = rootProject.file("gradle/configure-source-sets.gradle")) + +kotlin { + sourceSets { + val commonMain by getting { + dependencies { + api(project(":kotlinx-serialization-core")) + api(project(":kotlinx-serialization-json")) + implementation("com.squareup.okio:okio:${property("okio_version")}") + } + } + val commonTest by getting { + dependencies { + implementation("com.squareup.okio:okio:${property("okio_version")}") + } + } + } +} + +project.configureJava9ModuleInfo() diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt new file mode 100644 index 000000000..b666d839a --- /dev/null +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -0,0 +1,139 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.okio + +import kotlinx.serialization.* +import kotlinx.serialization.json.DecodeSequenceMode +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.internal.* +import kotlinx.serialization.json.okio.internal.JsonToOkioStreamWriter +import kotlinx.serialization.json.internal.decodeToSequenceByReader +import kotlinx.serialization.json.okio.internal.OkioSerialReader +import okio.* + +/** + * Serializes the [value] with [serializer] into a [target] using JSON format and UTF-8 encoding. + * + * If [target] is not a [BufferedSink] then called [Sink.buffer] for it to create buffered wrapper. + * + * @throws [SerializationException] if the given value cannot be serialized to JSON. + * @throws [okio.IOException] If an I/O error occurs and sink can't be written to. + */ +@ExperimentalSerializationApi +public fun Json.encodeToSink( + serializer: SerializationStrategy, + value: T, + target: Sink +) { + val buffered = if (target is BufferedSink) target else target.buffer() + val writer = JsonToOkioStreamWriter(buffered) + try { + encodeByWriter(writer, serializer, value) + } finally { + writer.release() + } +} + +/** + * Serializes given [value] to a [target] using UTF-8 encoding and serializer retrieved from the reified type parameter. + * + * If [target] is not a [BufferedSink] then called [Sink.buffer] for it to create buffered wrapper. + * + * @throws [SerializationException] if the given value cannot be serialized to JSON. + * @throws [okio.IOException] If an I/O error occurs and sink can't be written to. + */ +@ExperimentalSerializationApi +public inline fun Json.encodeToSink( + value: T, + target: Sink +): Unit = encodeToSink(serializersModule.serializer(), value, target) + + +/** + * Deserializes JSON from [source] using UTF-8 encoding to a value of type [T] using [deserializer]. + * + * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * + * Note that this functions expects that exactly one object would be present in the source + * and throws an exception if there are any dangling bytes after an object. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [okio.IOException] If an I/O error occurs and source can't be read from. + */ +@ExperimentalSerializationApi +public fun Json.decodeFromSource( + deserializer: DeserializationStrategy, + source: Source +): T { + val buffered = if (source is BufferedSource) source else source.buffer() + return decodeByReader(deserializer, OkioSerialReader(buffered)) +} + +/** + * Deserializes the contents of given [source] to the value of type [T] using UTF-8 encoding and + * deserializer retrieved from the reified type parameter. + * + * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * + * Note that this functions expects that exactly one object would be present in the stream + * and throws an exception if there are any dangling bytes after an object. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [okio.IOException] If an I/O error occurs and source can't be read from. + */ +@ExperimentalSerializationApi +public inline fun Json.decodeFromSource(source: Source): T = + decodeFromSource(serializersModule.serializer(), source) + + +/** + * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. + * Unlike [decodeFromSource], [source] is allowed to have more than one element, separated as [format] declares. + * + * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * + * Elements must all be of type [T]. + * Elements are parsed lazily when resulting [Sequence] is evaluated. + * Resulting sequence is tied to the stream and can be evaluated only once. + * + * **Resource caution:** this method neither closes the [source] when the parsing is finished nor provides a method to close it manually. + * It is a caller responsibility to hold a reference to a stream and close it. Moreover, because stream is parsed lazily, + * closing it before returned sequence is evaluated completely will result in [Exception] from decoder. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [okio.IOException] If an I/O error occurs and source can't be read from. + */ +@ExperimentalSerializationApi +public fun Json.decodeSourceToSequence( + source: Source, + deserializer: DeserializationStrategy, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence { + val buffered = if (source is BufferedSource) source else source.buffer() + return decodeToSequenceByReader(OkioSerialReader(buffered), deserializer, format) +} + +/** + * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and deserializer retrieved from the reified type parameter. + * Unlike [decodeFromSource], [source] is allowed to have more than one element, separated as [format] declares. + * + * If [source] is not a [BufferedSource] then called [Source.buffer] for it to create buffered wrapper. + * + * Elements must all be of type [T]. + * Elements are parsed lazily when resulting [Sequence] is evaluated. + * Resulting sequence is tied to the stream and constrained to be evaluated only once. + * + * **Resource caution:** this method does not close [source] when the parsing is finished neither provides method to close it manually. + * It is a caller responsibility to hold a reference to a stream and close it. Moreover, because stream is parsed lazily, + * closing it before returned sequence is evaluated fully would result in [Exception] from decoder. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [okio.IOException] If an I/O error occurs and source can't be read from. + */ +@ExperimentalSerializationApi +public inline fun Json.decodeSourceToSequence( + source: Source, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence = decodeSourceToSequence(source, serializersModule.serializer(), format) diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt new file mode 100644 index 000000000..3537392b2 --- /dev/null +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") + +package kotlinx.serialization.json.okio.internal + +import kotlinx.serialization.json.internal.ESCAPE_STRINGS +import kotlinx.serialization.json.internal.JsonWriter +import kotlinx.serialization.json.internal.SerialReader +import okio.* + +internal class JsonToOkioStreamWriter(private val target: BufferedSink) : JsonWriter { + override fun writeLong(value: Long) { + write(value.toString()) + } + + override fun writeChar(char: Char) { + target.writeUtf8CodePoint(char.code) + } + + override fun write(text: String) { + target.writeUtf8(text) + } + + override fun writeQuoted(text: String) { + target.writeUtf8CodePoint('"'.code) + var lastPos = 0 + for (i in text.indices) { + val c = text[i].code + if (c < ESCAPE_STRINGS.size && ESCAPE_STRINGS[c] != null) { + target.writeUtf8(text, lastPos, i) // flush prev + target.writeUtf8(ESCAPE_STRINGS[c]!!) + lastPos = i + 1 + } + } + + if (lastPos != 0) target.writeUtf8(text, lastPos, text.length) + else target.writeUtf8(text) + target.writeUtf8CodePoint('"'.code) + } + + override fun release() { + target.flush() + } +} + +internal class OkioSerialReader(private val source: BufferedSource): SerialReader { + override fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int { + var i = 0 + while (i < count && !source.exhausted()) { + buffer[i] = source.readUtf8CodePoint().toChar() + i++ + } + return if (i > 0) i else -1 + } +} + diff --git a/formats/json-okio/gradle.properties b/formats/json-okio/gradle.properties new file mode 100644 index 000000000..9965c652b --- /dev/null +++ b/formats/json-okio/gradle.properties @@ -0,0 +1 @@ +kotlin.mpp.enableCompatibilityMetadataVariant=false diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts new file mode 100644 index 000000000..5e18b6078 --- /dev/null +++ b/formats/json-tests/build.gradle.kts @@ -0,0 +1,50 @@ +/* + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ +import Java9Modularity.configureJava9ModuleInfo + +plugins { + kotlin("multiplatform") + kotlin("plugin.serialization") +} + +apply(from = rootProject.file("gradle/native-targets.gradle")) +apply(from = rootProject.file("gradle/configure-source-sets.gradle")) + +tasks.withType { + if (this.name == "compileTestKotlinJsLegacy") { + this.exclude("**/PropertyInitializerTest.kt") + } +} + +// disable kover tasks because there are no non-test classes in the project +tasks.named("koverHtmlReport") { + enabled = false +} +tasks.named("koverXmlReport") { + enabled = false +} +tasks.named("koverVerify") { + enabled = false +} + +kotlin { + sourceSets { + val commonTest by getting { + dependencies { + api(project(":kotlinx-serialization-json")) + api(project(":kotlinx-serialization-json-okio")) + implementation("com.squareup.okio:okio:${property("okio_version")}") + } + } + + val jvmTest by getting { + dependencies { + implementation("com.google.code.gson:gson:2.8.5") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${property("coroutines_version")}") + } + } + } +} + +project.configureJava9ModuleInfo() diff --git a/formats/json/commonTest/src/kotlinx/serialization/ClassWithMultipleMasksTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/ClassWithMultipleMasksTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/ClassWithMultipleMasksTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/ClassWithMultipleMasksTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/EncodingCollectionsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/EncodingCollectionsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/EncodingCollectionsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/EncodingCollectionsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/EncodingExtensionsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/EncodingExtensionsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/EncodingExtensionsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/EncodingExtensionsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/GenericSerializersOnFileTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/GenericSerializersOnFileTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/GenericSerializersOnFileTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/GenericSerializersOnFileTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/JsonOverwriteKeyTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/JsonOverwriteKeyTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/JsonOverwriteKeyTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/JsonOverwriteKeyTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/JsonPathTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/JsonPathTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/JsonPathTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/JsonPathTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt similarity index 96% rename from formats/json/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt index b44a37f3b..bd928ddb2 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt @@ -86,7 +86,11 @@ class NotNullSerializersCompatibilityOnFileTest { val json = Json { serializersModule = module } assertEquals("""{"nullable":null,"nonNullable":"foo"}""", json.encodeToString(FileContextualHolder(null, FileContextualType("foo")))) - assertEquals("""{"nullable":"foo","nonNullable":"bar"}""", json.encodeToString(FileContextualHolder(FileContextualType("foo"), FileContextualType("bar")))) + assertEquals("""{"nullable":"foo","nonNullable":"bar"}""", json.encodeToString( + FileContextualHolder( + FileContextualType("foo"), FileContextualType("bar") + ) + )) assertEquals(FileContextualHolder(null, FileContextualType("foo")), json.decodeFromString("""{"nullable":null,"nonNullable":"foo"}""")) assertEquals(FileContextualHolder(FileContextualType("foo"), FileContextualType("bar")), json.decodeFromString("""{"nullable":"foo","nonNullable":"bar"}""")) diff --git a/formats/json/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializableClasses.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/SerializableClasses.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/SerializableClasses.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/SerializableClasses.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializationForNullableTypeOnFileTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/SerializationForNullableTypeOnFileTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/SerializationForNullableTypeOnFileTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/SerializationForNullableTypeOnFileTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializerForNullableTypeTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/SerializerForNullableTypeTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/SerializerForNullableTypeTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/SerializerForNullableTypeTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/TuplesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/TuplesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/TuplesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/TuplesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/UmbrellaTypes.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/UmbrellaTypes.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/UmbrellaTypes.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/UmbrellaTypes.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/UnknownElementIndexTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/UnknownElementIndexTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/UnknownElementIndexTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/UnknownElementIndexTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/builtins/KeyValueSerializersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/builtins/KeyValueSerializersTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/builtins/KeyValueSerializersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/builtins/KeyValueSerializersTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/BinaryPayloadExampleTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/BinaryPayloadExampleTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/BinaryPayloadExampleTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/BinaryPayloadExampleTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt similarity index 93% rename from formats/json/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt index ca8116a0b..022ef0eb7 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt @@ -5,9 +5,7 @@ package kotlinx.serialization.features import kotlinx.serialization.* -import kotlinx.serialization.builtins.* import kotlinx.serialization.json.Json -import kotlinx.serialization.test.* import kotlin.test.* class CollectionSerializerTest { diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt similarity index 98% rename from formats/json/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt index 8f00ad97d..ac24cf04c 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt @@ -69,7 +69,8 @@ class ContextAndPolymorphicTest { @Test fun testReadCustom() { - val s = json.decodeFromString(EnhancedData.serializer(), + val s = json.decodeFromString( + EnhancedData.serializer(), """{"data":{"a":100500,"b":42},"stringPayload":{"s":"string"},"binaryPayload":"62696E617279"}""") assertEquals(value, s) } diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt similarity index 92% rename from formats/json/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt index d2f09f06b..9d35a2904 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt @@ -28,7 +28,8 @@ class DefaultPolymorphicSerializerTest : JsonTestBase() { @Test fun test() = parametrizedTest { - assertEquals(DefaultProject("example", "unknown"), + assertEquals( + DefaultProject("example", "unknown"), json.decodeFromString(""" {"type":"unknown","name":"example"}""", it)) } diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/DerivedContextualSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/DerivedContextualSerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/DerivedContextualSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/DerivedContextualSerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/DurationTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/DurationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/DurationTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt similarity index 98% rename from formats/json/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt index 804dca6c4..d246f0a11 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt @@ -99,7 +99,7 @@ class GenericCustomSerializerTest { fun testContextualGeneric() { val module = SerializersModule { @Suppress("UNCHECKED_CAST") - contextual(CheckedData::class) { args -> CheckedDataSerializer(args[0] as KSerializer)} + contextual(CheckedData::class) { args -> CheckedDataSerializer(args[0] as KSerializer) } } assertStringFormAndRestored( """{"data":{"data":"my data","checkSum":"2A20"}}""", diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/InheritanceTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/InheritanceTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/InheritanceTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/InheritanceTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/JsonClassDiscriminatorTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/JsonClassDiscriminatorTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/JsonClassDiscriminatorTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/JsonClassDiscriminatorTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/JsonNamesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/JsonNamesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/JsonNamesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/JsonNamesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/LocalClassesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/LocalClassesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/LocalClassesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/LocalClassesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/LongAsStringTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/LongAsStringTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/LongAsStringTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/LongAsStringTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/ObjectSerialization.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/ObjectSerialization.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/ObjectSerialization.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/ObjectSerialization.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PartiallyCustomSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PartiallyCustomSerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/PartiallyCustomSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PartiallyCustomSerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PolymorphicOnClassesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphicOnClassesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/PolymorphicOnClassesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphicOnClassesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt similarity index 99% rename from formats/json/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt index 9ce0ea9bf..e1d38fdd5 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt @@ -9,7 +9,6 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.modules.* import kotlinx.serialization.modules.plus import kotlinx.serialization.test.assertStringFormAndRestored -import kotlinx.serialization.test.isJs import kotlin.test.* class PolymorphismWithAnyTest { diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PrimitiveArraySerializersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PrimitiveArraySerializersTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/PrimitiveArraySerializersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PrimitiveArraySerializersTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/PropertyInitializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PropertyInitializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/PropertyInitializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/PropertyInitializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt similarity index 99% rename from formats/json/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt index 8af90553d..a99c2a1d5 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt @@ -11,7 +11,6 @@ import kotlinx.serialization.features.sealed.SealedParent import kotlinx.serialization.internal.* import kotlinx.serialization.json.* import kotlinx.serialization.modules.* -import kotlinx.serialization.test.* import kotlin.test.* class SealedClassesSerializationTest : JsonTestBase() { diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/SealedPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SealedPolymorphismTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/SealedPolymorphismTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/SealedPolymorphismTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/SerializableOnTypeUsageTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SerializableOnTypeUsageTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/SerializableOnTypeUsageTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/SerializableOnTypeUsageTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/SerializableWithTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SerializableWithTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/SerializableWithTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/SerializableWithTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/SkipDefaults.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/SkipDefaults.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/SkipDefaults.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/SkipDefaults.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/UseSerializersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/UseSerializersTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/UseSerializersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/UseSerializersTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/inline/EncodeInlineElementTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/EncodeInlineElementTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/inline/EncodeInlineElementTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/EncodeInlineElementTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineClassesCompleteTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineClassesCompleteTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineClassesCompleteTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineClassesCompleteTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineClassesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineClassesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineClassesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineClassesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineMapQuotedTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineMapQuotedTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/inline/InlineMapQuotedTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/InlineMapQuotedTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/inline/UnsignedIntegersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/UnsignedIntegersTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/inline/UnsignedIntegersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/inline/UnsignedIntegersTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedChild.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedChild.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedChild.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedChild.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedDiamondTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedDiamondTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedDiamondTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedDiamondTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedParent.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedParent.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedParent.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/features/sealed/SealedParent.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/AbstractJsonImplicitNullsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/AbstractJsonImplicitNullsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/AbstractJsonImplicitNullsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/AbstractJsonImplicitNullsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/BasicTypesSerializationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/BasicTypesSerializationTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/BasicTypesSerializationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/BasicTypesSerializationTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/DecodeFromJsonElementTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/DecodeFromJsonElementTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/DecodeFromJsonElementTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/DecodeFromJsonElementTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt similarity index 93% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt index 1e6b20ded..fd8d516c7 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt @@ -6,6 +6,7 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.json.internal.* +import kotlinx.serialization.test.assertFailsWithSerial import kotlin.test.* class JsonCoerceInputValuesTest : JsonTestBase() { @@ -60,10 +61,10 @@ class JsonCoerceInputValuesTest : JsonTestBase() { WithEnum(), WithEnum.serializer() ) - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { json.decodeFromString(WithEnum.serializer(), """{"e":{"x":"definitely not a valid enum value"}}""") } - assertFailsWith { // test user still sees exception on missing quotes + assertFailsWithSerial("JsonDecodingException") { // test user still sees exception on missing quotes Json(json) { isLenient = false }.decodeFromString(WithEnum.serializer(), """{"e":unknown_value}""") } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonConfigurationTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonConfigurationTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonConfigurationTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonConfigurationTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt similarity index 98% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt index 91b65d9be..bad5f962a 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt @@ -199,7 +199,7 @@ class JsonCustomSerializersTest : JsonTestBase() { fun testReadListOfOptional() = parametrizedTest { jsonTestingMode -> val obj = listOf(C(a = 1), C(b = 2), C(3, 4)) val j = """[{"b":42,"a":1},{"b":2},{"b":4,"a":3}]""" - val s = jsonNoAltNames.decodeFromString(ListSerializer(C), j, jsonTestingMode) + val s = jsonNoAltNames.decodeFromString(ListSerializer(C), j, jsonTestingMode) assertEquals(obj, s) } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonDefaultContextTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonDefaultContextTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonDefaultContextTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonDefaultContextTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonElementDecodingTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonElementDecodingTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonElementDecodingTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonElementDecodingTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonEncoderDecoderRecursiveTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonEncoderDecoderRecursiveTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonEncoderDecoderRecursiveTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonEncoderDecoderRecursiveTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonGenericTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonGenericTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonGenericTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonGenericTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonImplicitNullsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonImplicitNullsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonImplicitNullsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonImplicitNullsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt similarity index 93% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt index e958cca74..5ef340156 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt @@ -8,10 +8,8 @@ import kotlinx.serialization.* import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.descriptors.buildSerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -import kotlinx.serialization.json.internal.* import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.test.* import kotlin.jvm.* @@ -81,10 +79,9 @@ class JsonMapKeysTest : JsonTestBase() { } private inline fun verifyProhibition(value: T, streaming: JsonTestingMode) { - val e = assertFailsWith { + assertFailsWithSerialMessage("JsonEncodingException", "can't be used in JSON as a key in the map") { Json.encodeToString(value, streaming) } - assertTrue(e.message?.contains("can't be used in JSON as a key in the map") == true) } @Test @@ -143,7 +140,7 @@ class JsonMapKeysTest : JsonTestBase() { WithContextualKey(mapOf(ContextualValue("fooKey") to 1)), """{"map":{"fooKey":1}}""", Json { - serializersModule = SerializersModule { contextual(ContextualValue::class, ContextualValue.Companion) } + serializersModule = SerializersModule { contextual(ContextualValue::class, ContextualValue) } } ) } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonModesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonModesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonModesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonModesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonNumericKeysTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonNumericKeysTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonNumericKeysTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonNumericKeysTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonOptionalTests.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonOptionalTests.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonOptionalTests.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonOptionalTests.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt similarity index 53% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt index 87b0f3582..892696b8c 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt @@ -5,7 +5,6 @@ package kotlinx.serialization.json import kotlinx.serialization.* -import kotlinx.serialization.json.internal.* import kotlinx.serialization.test.* import kotlin.test.* @@ -18,35 +17,35 @@ class JsonParserFailureModesTest : JsonTestBase() { @Test fun testFailureModes() = parametrizedTest { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id": "}""", it ) } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id": ""}""", it ) } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id":a}""", it ) } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id":2.0}""", it ) } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id2":2}""", @@ -54,7 +53,7 @@ class JsonParserFailureModesTest : JsonTestBase() { ) } // 9223372036854775807 is Long.MAX_VALUE - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id":${Long.MAX_VALUE}""" + "00" + "}", @@ -62,21 +61,21 @@ class JsonParserFailureModesTest : JsonTestBase() { ) } // -9223372036854775808 is Long.MIN_VALUE - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( Holder.serializer(), """{"id":9223372036854775808}""", it ) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{"id"}""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{"id}""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{"i}""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{"}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{"id"}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{"id}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{"i}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{"}""", it) } assertFailsWithMissingField { default.decodeFromString(Holder.serializer(), """{}""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """}""", it) } - assertFailsWith { default.decodeFromString(Holder.serializer(), """{""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), """{""", it) } } @Serializable @@ -84,14 +83,14 @@ class JsonParserFailureModesTest : JsonTestBase() { @Test fun testBoolean() = parametrizedTest { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( BooleanHolder.serializer(), """{"b": fals}""", it ) } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( BooleanHolder.serializer(), """{"b": 123}""", @@ -108,11 +107,11 @@ class JsonParserFailureModesTest : JsonTestBase() { @Test fun testOverflow() = parametrizedTest { // Byte overflow - assertFailsWith { default.decodeFromString("""{"b": 128}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"b": 128}""", it) } // Short overflow - assertFailsWith { default.decodeFromString("""{"s": 32768}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"s": 32768}""", it) } // Int overflow - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString( """{"i": 2147483648}""", it @@ -134,14 +133,14 @@ class JsonParserFailureModesTest : JsonTestBase() { @Test fun testInvalidNumber() = parametrizedTest { - assertFailsWith { default.decodeFromString("""{"id":-}""", it) } - assertFailsWith { default.decodeFromString("""{"id":+}""", it) } - assertFailsWith { default.decodeFromString("""{"id":--}""", it) } - assertFailsWith { default.decodeFromString("""{"id":1-1}""", it) } - assertFailsWith { default.decodeFromString("""{"id":0-1}""", it) } - assertFailsWith { default.decodeFromString("""{"id":0-}""", it) } - assertFailsWith { default.decodeFromString("""{"id":a}""", it) } - assertFailsWith { default.decodeFromString("""{"id":-a}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":-}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":+}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":--}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":1-1}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":0-1}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":0-}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":a}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"id":-a}""", it) } } @@ -153,9 +152,9 @@ class JsonParserFailureModesTest : JsonTestBase() { @Test fun testUnexpectedNull() = parametrizedTest { - assertFailsWith { default.decodeFromString("""{"b":{"b":"b"}}""", it) } - assertFailsWith { default.decodeFromString("""{"b":null}""", it) } - assertFailsWith { default.decodeFromString("""{"s":{"s":"s"}}""", it) } - assertFailsWith { default.decodeFromString("""{"s":null}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"b":{"b":"b"}}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"b":null}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"s":{"s":"s"}}""", it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString("""{"s":null}""", it) } } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt similarity index 85% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt index 123214e21..7f9044f9d 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt @@ -16,7 +16,7 @@ class JsonParserTest : JsonTestBase() { fun testQuotedBrace() { val tree = parse("""{"x": "{"}""") assertTrue("x" in tree) - assertEquals("{", (tree.getValue("x") as JsonLiteral).content) + assertEquals("{", (tree.getValue("x") as JsonPrimitive).content) } private fun parse(input: String) = default.parseToJsonElement(input).jsonObject @@ -25,19 +25,19 @@ class JsonParserTest : JsonTestBase() { fun testEmptyKey() { val tree = parse("""{"":"","":""}""") assertTrue("" in tree) - assertEquals("", (tree.getValue("") as JsonLiteral).content) + assertEquals("", (tree.getValue("") as JsonPrimitive).content) } @Test fun testEmptyValue() { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { parse("""{"X": "foo", "Y"}""") } } @Test fun testIncorrectUnicodeEscape() { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { parse("""{"X": "\uDD1H"}""") } } @@ -83,18 +83,16 @@ class JsonParserTest : JsonTestBase() { } private fun testTrailingComma(content: String) { - val e = assertFailsWith { Json.parseToJsonElement(content) } - val msg = e.message!! - assertTrue(msg.contains("Unexpected trailing")) + assertFailsWithSerialMessage("JsonDecodingException", "Unexpected trailing") { Json.parseToJsonElement(content) } } @Test fun testUnclosedStringLiteral() { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { parse("\"") } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { parse("""{"id":"""") } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonReifiedCollectionsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonReifiedCollectionsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonReifiedCollectionsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonReifiedCollectionsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonRootLevelNullTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonRootLevelNullTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonRootLevelNullTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonRootLevelNullTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonSealedSubclassTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonSealedSubclassTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonSealedSubclassTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonSealedSubclassTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt similarity index 84% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt index 4352aa6bf..33f23b819 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt @@ -1,19 +1,24 @@ /* - * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2017-2022 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 kotlinx.serialization.json.internal.* +import kotlinx.serialization.json.okio.decodeFromSource +import kotlinx.serialization.json.okio.encodeToSink import kotlinx.serialization.modules.EmptySerializersModule import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.test.* import kotlin.test.assertEquals +import okio.* + enum class JsonTestingMode { STREAMING, TREE, + OKIO_STREAMS, JAVA_STREAMS; companion object { @@ -46,6 +51,11 @@ abstract class JsonTestBase { val tree = writeJson(value, serializer) encodeToString(tree) } + JsonTestingMode.OKIO_STREAMS -> { + val buffer = Buffer() + encodeToSink(serializer, value, buffer) + buffer.readUtf8() + } } internal inline fun Json.decodeFromString(source: String, jsonTestingMode: JsonTestingMode): T { @@ -66,18 +76,22 @@ abstract class JsonTestBase { decodeViaStream(deserializer, source) } JsonTestingMode.TREE -> { - val lexer = StringJsonLexer(source) - val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor, null) - val tree = input.decodeJsonElement() - lexer.expectEof() + val tree = decodeStringToJsonTree(deserializer, source) readJson(tree, deserializer) } + JsonTestingMode.OKIO_STREAMS -> { + val buffer = Buffer() + buffer.writeUtf8(source) + decodeFromSource(deserializer, buffer) + } } protected open fun parametrizedTest(test: (JsonTestingMode) -> Unit) { processResults(buildList { add(runCatching { test(JsonTestingMode.STREAMING) }) add(runCatching { test(JsonTestingMode.TREE) }) + add(runCatching { test(JsonTestingMode.OKIO_STREAMS) }) + if (isJvm()) { add(runCatching { test(JsonTestingMode.JAVA_STREAMS) }) } @@ -101,7 +115,8 @@ abstract class JsonTestBase { protected fun parametrizedTest(json: Json, test: StringFormat.() -> Unit) { val streamingResult = runCatching { SwitchableJson(json, JsonTestingMode.STREAMING).test() } val treeResult = runCatching { SwitchableJson(json, JsonTestingMode.TREE).test() } - processResults(listOf(streamingResult, treeResult)) + val okioResult = runCatching { SwitchableJson(json, JsonTestingMode.OKIO_STREAMS).test() } + processResults(listOf(streamingResult, treeResult, okioResult)) } protected fun processResults(results: List>) { diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTransformingSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTransformingSerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTransformingSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTransformingSerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt similarity index 94% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt index c46a11d51..ebe063138 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt @@ -8,6 +8,7 @@ package kotlinx.serialization.json import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.json.internal.* +import kotlinx.serialization.test.assertFailsWithSerial import kotlin.test.* class JsonTransientTest : JsonTestBase() { @@ -51,7 +52,7 @@ class JsonTransientTest : JsonTestBase() { @Test fun testThrowTransient() = parametrizedTest { jsonTestingMode -> - assertFailsWith(JsonDecodingException::class) { + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Data.serializer(), """{"a":0,"b":100500,"c":"Hello"}""", jsonTestingMode) } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeImplicitNullsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeImplicitNullsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeImplicitNullsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeImplicitNullsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt similarity index 99% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt index 3506e1f8b..6e600386b 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt @@ -7,7 +7,6 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.test.* import kotlin.test.* -import kotlin.test.assertTrue class JsonTreeTest : JsonTestBase() { @Serializable diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonUnicodeTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUnicodeTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonUnicodeTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUnicodeTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonUnionEnumTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUnionEnumTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonUnionEnumTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUnionEnumTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/JsonUpdateModeTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUpdateModeTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/JsonUpdateModeTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonUpdateModeTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/LenientTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/LenientTest.kt similarity index 84% rename from formats/json/commonTest/src/kotlinx/serialization/json/LenientTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/LenientTest.kt index b89e853f6..41d3c2c20 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/LenientTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/LenientTest.kt @@ -7,6 +7,7 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.builtins.* import kotlinx.serialization.json.internal.* +import kotlinx.serialization.test.assertFailsWithSerial import kotlin.test.* class LenientTest : JsonTestBase() { @@ -36,28 +37,28 @@ class LenientTest : JsonTestBase() { @Test fun testQuotedBoolean() = parametrizedTest { val json = """{"i":1, "l":2, "b":"true", "s":"string"}""" - assertFailsWith { default.decodeFromString(Holder.serializer(), json, it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), json, it) } assertEquals(value, lenient.decodeFromString(Holder.serializer(), json, it)) } @Test fun testUnquotedStringValue() = parametrizedTest { val json = """{"i":1, "l":2, "b":true, "s":string}""" - assertFailsWith { default.decodeFromString(Holder.serializer(), json, it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), json, it) } assertEquals(value, lenient.decodeFromString(Holder.serializer(), json, it)) } @Test fun testUnquotedKey() = parametrizedTest { val json = """{"i":1, "l":2, b:true, "s":"string"}""" - assertFailsWith { default.decodeFromString(Holder.serializer(), json, it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(Holder.serializer(), json, it) } assertEquals(value, lenient.decodeFromString(Holder.serializer(), json, it)) } @Test fun testUnquotedStringInArray() = parametrizedTest { val json = """{"l":[1, 2, ss]}""" - assertFailsWith { default.decodeFromString(ListHolder.serializer(), json, it) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(ListHolder.serializer(), json, it) } assertEquals(listValue, lenient.decodeFromString(ListHolder.serializer(), json, it)) } @@ -68,7 +69,7 @@ class LenientTest : JsonTestBase() { fun testNullsProhibited() = parametrizedTest { assertEquals(StringWrapper("nul"), lenient.decodeFromString("""{"s":nul}""", it)) assertEquals(StringWrapper("null1"), lenient.decodeFromString("""{"s":null1}""", it)) - assertFailsWith { lenient.decodeFromString("""{"s":null}""", it) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString("""{"s":null}""", it) } } @Serializable diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/MapLikeSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/MapLikeSerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/MapLikeSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/MapLikeSerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt similarity index 82% rename from formats/json/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt index 745b0747b..fad07e620 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt @@ -47,11 +47,9 @@ class SpecialFloatingPointValuesTest : JsonTestBase() { } private fun test(box: Box, expected: String, jsonTestingMode: JsonTestingMode) { - val e1 = assertFailsWith { default.encodeToString(Box.serializer(), box, jsonTestingMode) } - assertTrue { e1.message!!.contains("Unexpected special floating-point value") } + assertFailsWithSerialMessage("JsonEncodingException", "Unexpected special floating-point value") { default.encodeToString(Box.serializer(), box, jsonTestingMode) } assertEquals(expected, json.encodeToString(Box.serializer(), box, jsonTestingMode)) assertEquals(box, json.decodeFromString(Box.serializer(), expected, jsonTestingMode)) - val e2 = assertFailsWith { default.decodeFromString(Box.serializer(), expected, jsonTestingMode) } - assertTrue { e2.message!!.contains("Unexpected special floating-point value") } + assertFailsWithSerialMessage("JsonDecodingException", "Unexpected special floating-point value") { default.decodeFromString(Box.serializer(), expected, jsonTestingMode) } } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt similarity index 88% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt index 13e92316d..b7d4f1226 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt @@ -8,6 +8,7 @@ import kotlinx.serialization.* import kotlinx.serialization.json.* import kotlinx.serialization.json.internal.* import kotlinx.serialization.modules.* +import kotlinx.serialization.test.assertFailsWithSerial import kotlin.test.* class JsonPolymorphismExceptionTest : JsonTestBase() { @@ -30,7 +31,7 @@ class JsonPolymorphismExceptionTest : JsonTestBase() { } } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { Json { serializersModule = serialModule }.decodeFromString(Base.serializer(), """{"type":"derived","nested":null}""", jsonTestingMode) } } @@ -43,7 +44,7 @@ class JsonPolymorphismExceptionTest : JsonTestBase() { } } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { Json { serializersModule = serialModule }.decodeFromString(Base.serializer(), """{"nested":{}}""", jsonTestingMode) } } diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt similarity index 83% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt index ba4672a13..c571ec9ed 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt @@ -5,7 +5,6 @@ package kotlinx.serialization.json.serializers import kotlinx.serialization.json.* -import kotlinx.serialization.json.internal.* import kotlinx.serialization.test.* import kotlin.test.* @@ -27,22 +26,22 @@ class JsonArraySerializerTest : JsonTestBase() { @Test fun testTopLevelJsonObjectAsElement() = parametrizedTest(default) { - assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonElementSerializer) + assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonElement.serializer()) } @Test fun testJsonArrayToString() { val prebuiltJson = prebuiltJson() - val string = lenient.encodeToString(JsonArraySerializer, prebuiltJson) + val string = lenient.encodeToString(JsonArray.serializer(), prebuiltJson) assertEquals(string, prebuiltJson.toString()) } @Test fun testMixedLiterals() = parametrizedTest { jsonTestingMode -> val json = """[1, "2", 3, "4"]""" - val array = default.decodeFromString(JsonArraySerializer, json, jsonTestingMode) + val array = default.decodeFromString(JsonArray.serializer(), json, jsonTestingMode) array.forEachIndexed { index, element -> - require(element is JsonLiteral) + require(element is JsonPrimitive) assertEquals(index % 2 == 1, element.isString) } } @@ -58,17 +57,17 @@ class JsonArraySerializerTest : JsonTestBase() { @Test fun testEmptyArray() = parametrizedTest { jsonTestingMode -> - assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArraySerializer, "[]", jsonTestingMode)) - assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArraySerializer, "[ ]", jsonTestingMode)) - assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArraySerializer, "[\n\n]", jsonTestingMode)) - assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArraySerializer, "[ \t]", jsonTestingMode)) + assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArray.serializer(), "[]", jsonTestingMode)) + assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArray.serializer(), "[ ]", jsonTestingMode)) + assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArray.serializer(), "[\n\n]", jsonTestingMode)) + assertEquals(JsonArray(emptyList()), lenient.decodeFromString(JsonArray.serializer(), "[ \t]", jsonTestingMode)) } @Test fun testWhitespaces() = parametrizedTest { jsonTestingMode -> assertEquals( JsonArray(listOf(1, 2, 3, 4, 5).map(::JsonPrimitive)), - lenient.decodeFromString(JsonArraySerializer, "[1, 2, 3, \n 4, 5]", jsonTestingMode) + lenient.decodeFromString(JsonArray.serializer(), "[1, 2, 3, \n 4, 5]", jsonTestingMode) ) } @@ -89,9 +88,9 @@ class JsonArraySerializerTest : JsonTestBase() { } private fun testFails(input: String, errorMessage: String, jsonTestingMode: JsonTestingMode) { - assertFailsWithMessage(errorMessage) { + assertFailsWithSerial("JsonDecodingException", errorMessage) { lenient.decodeFromString( - JsonArraySerializer, + JsonArray.serializer(), input, jsonTestingMode ) diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonNativePrimitivesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonNativePrimitivesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonNativePrimitivesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonNativePrimitivesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt similarity index 69% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt index 83de5928c..934afcacc 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt @@ -5,7 +5,7 @@ package kotlinx.serialization.json.serializers import kotlinx.serialization.json.* -import kotlinx.serialization.json.internal.* +import kotlinx.serialization.test.assertFailsWithSerialMessage import kotlinx.serialization.test.assertStringFormAndRestored import kotlin.test.* @@ -18,8 +18,7 @@ class JsonNullSerializerTest : JsonTestBase() { @Test fun testJsonNullFailure() = parametrizedTest(default) { - val t = assertFailsWith { default.decodeFromString(JsonNullWrapper.serializer(), "{\"element\":\"foo\"}", JsonTestingMode.STREAMING) } - assertTrue { t.message!!.contains("'null' literal") } + assertFailsWithSerialMessage("JsonDecodingException", "'null' literal") { default.decodeFromString(JsonNullWrapper.serializer(), "{\"element\":\"foo\"}", JsonTestingMode.STREAMING) } } @Test @@ -34,28 +33,28 @@ class JsonNullSerializerTest : JsonTestBase() { @Test fun testTopLevelJsonNull() = parametrizedTest { jsonTestingMode -> - val string = default.encodeToString(JsonNullSerializer, JsonNull, jsonTestingMode) + val string = default.encodeToString(JsonNull.serializer(), JsonNull, jsonTestingMode) assertEquals("null", string) - assertEquals(JsonNull, default.decodeFromString(JsonNullSerializer, string, jsonTestingMode)) + assertEquals(JsonNull, default.decodeFromString(JsonNull.serializer(), string, jsonTestingMode)) } @Test fun testTopLevelJsonNullAsElement() = parametrizedTest { jsonTestingMode -> - val string = default.encodeToString(JsonElementSerializer, JsonNull, jsonTestingMode) + val string = default.encodeToString(JsonElement.serializer(), JsonNull, jsonTestingMode) assertEquals("null", string) - assertEquals(JsonNull, default.decodeFromString(JsonElementSerializer, string, jsonTestingMode)) + assertEquals(JsonNull, default.decodeFromString(JsonElement.serializer(), string, jsonTestingMode)) } @Test fun testTopLevelJsonNullAsPrimitive() = parametrizedTest { jsonTestingMode -> - val string = default.encodeToString(JsonPrimitiveSerializer, JsonNull, jsonTestingMode) + val string = default.encodeToString(JsonPrimitive.serializer(), JsonNull, jsonTestingMode) assertEquals("null", string) - assertEquals(JsonNull, default.decodeFromString(JsonPrimitiveSerializer, string, jsonTestingMode)) + assertEquals(JsonNull, default.decodeFromString(JsonPrimitive.serializer(), string, jsonTestingMode)) } @Test fun testJsonNullToString() { - val string = default.encodeToString(JsonPrimitiveSerializer, JsonNull) + val string = default.encodeToString(JsonPrimitive.serializer(), JsonNull) assertEquals(string, JsonNull.toString()) } } diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt new file mode 100644 index 000000000..9a65effe2 --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.json.serializers + +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.* +import kotlinx.serialization.json.internal.* +import kotlinx.serialization.test.* +import kotlin.test.* + +class JsonObjectSerializerTest : JsonTestBase() { + + private val expected = """{"element":{"literal":1,"nullKey":null,"nested":{"another literal":"some value"},"\\. escaped":"\\. escaped","\n new line":"\n new line"}}""" + private val expectedTopLevel = """{"literal":1,"nullKey":null,"nested":{"another literal":"some value"},"\\. escaped":"\\. escaped","\n new line":"\n new line"}""" + + @Test + fun testJsonObject() = parametrizedTest(default) { + assertStringFormAndRestored(expected, JsonObjectWrapper(prebuiltJson()), JsonObjectWrapper.serializer()) + } + + @Test + fun testJsonObjectAsElement() = parametrizedTest(default) { + assertStringFormAndRestored(expected, JsonElementWrapper(prebuiltJson()), JsonElementWrapper.serializer()) + } + + @Test + fun testTopLevelJsonObject() = parametrizedTest (default) { + assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonObject.serializer()) + } + + @Test + fun testTopLevelJsonObjectAsElement() = parametrizedTest (default) { + assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonElement.serializer()) + } + + @Test + fun testJsonObjectToString() { + val prebuiltJson = prebuiltJson() + val string = lenient.encodeToString(JsonElement.serializer(), prebuiltJson) + assertEquals(string, prebuiltJson.toString()) + } + + @Test + fun testDocumentationSample() { + val string = Json.encodeToString(JsonElement.serializer(), buildJsonObject { put("key", 1.0) }) + val literal = Json.decodeFromString(JsonElement.serializer(), string) + assertEquals(JsonObject(mapOf("key" to JsonPrimitive(1.0))), literal) + } + + @Test + fun testMissingCommas() = parametrizedTest { jsonTestingMode -> + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{ \"1\": \"2\" \"3\":\"4\"}", jsonTestingMode) } + } + + @Test + fun testEmptyObject() = parametrizedTest { jsonTestingMode -> + assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObject.serializer(), "{}", jsonTestingMode)) + assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObject.serializer(), "{}", jsonTestingMode)) + assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObject.serializer(), "{\n\n}", jsonTestingMode)) + assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObject.serializer(), "{ \t}", jsonTestingMode)) + } + + @Test + fun testInvalidObject() = parametrizedTest { jsonTestingMode -> + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(JsonObject.serializer(), "{\"a\":\"b\"]", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(JsonObject.serializer(), "{", jsonTestingMode) } + if (jsonTestingMode != JsonTestingMode.JAVA_STREAMS) // Streams support dangling characters + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(JsonObject.serializer(), "{}}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { default.decodeFromString(JsonObject.serializer(), "{]", jsonTestingMode) } + } + + @Test + fun testWhitespaces() = parametrizedTest { jsonTestingMode -> + assertEquals( + JsonObject(mapOf("1" to JsonPrimitive(2), "3" to JsonPrimitive(4), "5" to JsonPrimitive(6))), + lenient.decodeFromString(JsonObject.serializer(), "{1: 2, 3: \n 4, 5:6}", jsonTestingMode) + ) + } + + @Test + fun testExcessiveCommas() = parametrizedTest { jsonTestingMode -> + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{\"a\":\"b\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{\"a\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,\"1\":\"2\"}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,\"1\":\"2\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,,\"1\":\"2\"}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{\"1\":\"2\",,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{\"1\":\"2\",,\"2\":\"2\"}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{, ,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(JsonObject.serializer(), "{,\n,}", jsonTestingMode) } + } + + @Serializable + data class Holder(val a: String) + + @Test + fun testExcessiveCommasInObject() = parametrizedTest { jsonTestingMode -> + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{\"a\":\"b\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{\"a\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,\"a\":\"b\"}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,\"a\":\"b\",}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,,\"a\":\"b\"}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{\"a\":\"b\",,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{, ,}", jsonTestingMode) } + assertFailsWithSerial("JsonDecodingException") { lenient.decodeFromString(Holder.serializer(), "{,\n,}", jsonTestingMode) } + } + + private fun prebuiltJson(): JsonObject { + return buildJsonObject { + put("literal", 1) + put("nullKey", JsonNull) + putJsonObject("nested") { + put("another literal", "some value") + } + put("\\. escaped", "\\. escaped") + put("\n new line", "\n new line") + } + } +} diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt similarity index 87% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt index 789fb2ca9..dfa7f4c7f 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt @@ -48,30 +48,30 @@ class JsonPrimitiveSerializerTest : JsonTestBase() { @Test fun testTopLevelPrimitive() = parametrizedTest { jsonTestingMode -> - val string = default.encodeToString(JsonPrimitiveSerializer, JsonPrimitive(42), jsonTestingMode) + val string = default.encodeToString(JsonPrimitive.serializer(), JsonPrimitive(42), jsonTestingMode) assertEquals("42", string) - assertEquals(JsonPrimitive(42), default.decodeFromString(JsonPrimitiveSerializer, string)) + assertEquals(JsonPrimitive(42), default.decodeFromString(JsonPrimitive.serializer(), string)) } @Test fun testTopLevelPrimitiveAsElement() = parametrizedTest { jsonTestingMode -> if (isJs()) return@parametrizedTest // JS toString numbers - val string = default.encodeToString(JsonElementSerializer, JsonPrimitive(1.3), jsonTestingMode) + val string = default.encodeToString(JsonElement.serializer(), JsonPrimitive(1.3), jsonTestingMode) assertEquals("1.3", string) - assertEquals(JsonPrimitive(1.3), default.decodeFromString(JsonElementSerializer, string, jsonTestingMode)) + assertEquals(JsonPrimitive(1.3), default.decodeFromString(JsonElement.serializer(), string, jsonTestingMode)) } @Test fun testJsonLiteralStringToString() { val literal = JsonPrimitive("some string literal") - val string = default.encodeToString(JsonPrimitiveSerializer, literal) + val string = default.encodeToString(JsonPrimitive.serializer(), literal) assertEquals(string, literal.toString()) } @Test fun testJsonLiteralIntToString() { val literal = JsonPrimitive(0) - val string = default.encodeToString(JsonPrimitiveSerializer, literal) + val string = default.encodeToString(JsonPrimitive.serializer(), literal) assertEquals(string, literal.toString()) } @@ -93,7 +93,7 @@ class JsonPrimitiveSerializerTest : JsonTestBase() { private fun testLiteral(number: Number, jvmExpectedString: String) { val literal = JsonPrimitive(number) - val string = default.encodeToString(JsonPrimitiveSerializer, literal) + val string = default.encodeToString(JsonPrimitive.serializer(), literal) assertEquals(string, literal.toString()) if (isJvm()) { // We can rely on stable double/float format only on JVM assertEquals(string, jvmExpectedString) diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonSerializerInGenericsTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonSerializerInGenericsTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonSerializerInGenericsTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonSerializerInGenericsTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt similarity index 99% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt index 00a78a21d..dd4d51ef3 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt @@ -9,7 +9,7 @@ import kotlin.test.* class JsonTreeTest : JsonTestBase() { - private fun parse(input: String): JsonElement = default.decodeFromString(JsonElementSerializer, input) + private fun parse(input: String): JsonElement = default.decodeFromString(JsonElement.serializer(), input) @Test fun testParseWithoutExceptions() { diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/Primitives.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/Primitives.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/json/serializers/Primitives.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/Primitives.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionInSealedClassesTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionInSealedClassesTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionInSealedClassesTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionInSealedClassesTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/ContextualTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/ContextualTest.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/ContextualTest.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/ContextualTest.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/CurrentPlatform.common.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/CurrentPlatform.common.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/CurrentPlatform.common.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/CurrentPlatform.common.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/InternalHexConverter.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/InternalHexConverter.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/InternalHexConverter.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/InternalHexConverter.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/JsonHelpers.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/JsonHelpers.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/JsonHelpers.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/JsonHelpers.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/TestHelpers.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt similarity index 94% rename from formats/json/commonTest/src/kotlinx/serialization/test/TestHelpers.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt index d178c871c..04af40c6e 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/test/TestHelpers.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt @@ -1,6 +1,9 @@ /* - * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ + +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") + package kotlinx.serialization.test import kotlinx.serialization.* diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/TestId.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestId.kt similarity index 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/TestId.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/TestId.kt diff --git a/formats/json/commonTest/src/kotlinx/serialization/test/TestingFramework.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt similarity index 68% rename from formats/json/commonTest/src/kotlinx/serialization/test/TestingFramework.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt index 064828a8b..c31e4919c 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/test/TestingFramework.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt @@ -52,6 +52,35 @@ fun assertSerializedAndRestored( assertEquals(original, restored) } +inline fun assertFailsWithSerial( + exceptionName: String, + assertionMessage: String? = null, + block: () -> Unit +) { + val exception = assertFailsWith(SerializationException::class, assertionMessage, block) + assertEquals( + exceptionName, + exception::class.simpleName, + "Expected exception with type '${exceptionName}' but got '${exception::class.simpleName}'" + ) +} +inline fun assertFailsWithSerialMessage( + exceptionName: String, + message: String, + assertionMessage: String? = null, + block: () -> Unit +) { + val exception = assertFailsWith(SerializationException::class, assertionMessage, block) + assertEquals( + exceptionName, + exception::class.simpleName, + "Expected exception type '$exceptionName' but actual is '${exception::class.simpleName}'" + ) + assertTrue( + exception.message!!.contains(message), + "Expected message '${exception.message}' to contain substring '$message'" + ) +} inline fun assertFailsWithMessage( message: String, assertionMessage: String? = null, diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicSpecialCasesTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicSpecialCasesTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicSpecialCasesTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicSpecialCasesTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/DynamicPolymorphismTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicPolymorphismTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/DynamicPolymorphismTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicPolymorphismTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt similarity index 90% rename from formats/json/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt index 9c5011a81..2daf0bb2a 100644 --- a/formats/json/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt +++ b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt @@ -4,10 +4,14 @@ package kotlinx.serialization.json -import kotlinx.serialization.json.internal.* import kotlinx.serialization.* import kotlin.test.* +/** + * [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER] + */ +internal const val MAX_SAFE_INTEGER: Double = 9007199254740991.toDouble() // 2^53 - 1 + class DynamicToLongTest { @Serializable diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt similarity index 92% rename from formats/json/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt index ead189697..e41906443 100644 --- a/formats/json/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt +++ b/formats/json-tests/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt @@ -4,13 +4,8 @@ package kotlinx.serialization.json -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* import kotlinx.serialization.* -import kotlinx.serialization.modules.* -import kotlinx.serialization.test.* import kotlin.test.* -import kotlin.test.assertFailsWith class EncodeToDynamicSpecialCasesTest { diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/EncodeToDynamicTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/EncodeToDynamicTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/EncodeToDynamicTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/EncodeToDynamicTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/JsonCoerceInputValuesDynamicTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonCoerceInputValuesDynamicTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/JsonCoerceInputValuesDynamicTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonCoerceInputValuesDynamicTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/JsonDynamicImplicitNullsTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonDynamicImplicitNullsTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/JsonDynamicImplicitNullsTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonDynamicImplicitNullsTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/json/JsonNamesDynamicTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonNamesDynamicTest.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/JsonNamesDynamicTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/JsonNamesDynamicTest.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/test/CurrentPlatform.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/test/CurrentPlatform.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/test/CurrentPlatform.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/test/CurrentPlatform.kt diff --git a/formats/json/jsTest/src/kotlinx/serialization/test/JsonHelpers.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/test/JsonHelpers.kt similarity index 100% rename from formats/json/jsTest/src/kotlinx/serialization/test/JsonHelpers.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/test/JsonHelpers.kt diff --git a/formats/json/jvmTest/resources/corner_cases/listing.txt b/formats/json-tests/jvmTest/resources/corner_cases/listing.txt similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/listing.txt rename to formats/json-tests/jvmTest/resources/corner_cases/listing.txt diff --git a/formats/json/jvmTest/resources/corner_cases/number_1.0.json b/formats/json-tests/jvmTest/resources/corner_cases/number_1.0.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_1.0.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_1.0.json diff --git a/formats/json/jvmTest/resources/corner_cases/number_1.000000000000000005.json b/formats/json-tests/jvmTest/resources/corner_cases/number_1.000000000000000005.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_1.000000000000000005.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_1.000000000000000005.json diff --git a/formats/json/jvmTest/resources/corner_cases/number_1000000000000000.json b/formats/json-tests/jvmTest/resources/corner_cases/number_1000000000000000.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_1000000000000000.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_1000000000000000.json diff --git a/formats/json/jvmTest/resources/corner_cases/number_10000000000000000999.json b/formats/json-tests/jvmTest/resources/corner_cases/number_10000000000000000999.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_10000000000000000999.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_10000000000000000999.json diff --git a/formats/json/jvmTest/resources/corner_cases/number_1e-999.json b/formats/json-tests/jvmTest/resources/corner_cases/number_1e-999.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_1e-999.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_1e-999.json diff --git a/formats/json/jvmTest/resources/corner_cases/number_1e6.json b/formats/json-tests/jvmTest/resources/corner_cases/number_1e6.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/number_1e6.json rename to formats/json-tests/jvmTest/resources/corner_cases/number_1e6.json diff --git a/formats/json/jvmTest/resources/corner_cases/object_key_nfc_nfd.json b/formats/json-tests/jvmTest/resources/corner_cases/object_key_nfc_nfd.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/object_key_nfc_nfd.json rename to formats/json-tests/jvmTest/resources/corner_cases/object_key_nfc_nfd.json diff --git a/formats/json/jvmTest/resources/corner_cases/object_key_nfd_nfc.json b/formats/json-tests/jvmTest/resources/corner_cases/object_key_nfd_nfc.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/object_key_nfd_nfc.json rename to formats/json-tests/jvmTest/resources/corner_cases/object_key_nfd_nfc.json diff --git a/formats/json/jvmTest/resources/corner_cases/object_same_key_different_values.json b/formats/json-tests/jvmTest/resources/corner_cases/object_same_key_different_values.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/object_same_key_different_values.json rename to formats/json-tests/jvmTest/resources/corner_cases/object_same_key_different_values.json diff --git a/formats/json/jvmTest/resources/corner_cases/object_same_key_same_value.json b/formats/json-tests/jvmTest/resources/corner_cases/object_same_key_same_value.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/object_same_key_same_value.json rename to formats/json-tests/jvmTest/resources/corner_cases/object_same_key_same_value.json diff --git a/formats/json/jvmTest/resources/corner_cases/object_same_key_unclear_values.json b/formats/json-tests/jvmTest/resources/corner_cases/object_same_key_unclear_values.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/object_same_key_unclear_values.json rename to formats/json-tests/jvmTest/resources/corner_cases/object_same_key_unclear_values.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_1_escaped_invalid_codepoint.json b/formats/json-tests/jvmTest/resources/corner_cases/string_1_escaped_invalid_codepoint.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_1_escaped_invalid_codepoint.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_1_escaped_invalid_codepoint.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_1_invalid_codepoint.json b/formats/json-tests/jvmTest/resources/corner_cases/string_1_invalid_codepoint.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_1_invalid_codepoint.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_1_invalid_codepoint.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_2_escaped_invalid_codepoints.json b/formats/json-tests/jvmTest/resources/corner_cases/string_2_escaped_invalid_codepoints.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_2_escaped_invalid_codepoints.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_2_escaped_invalid_codepoints.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_2_invalid_codepoints.json b/formats/json-tests/jvmTest/resources/corner_cases/string_2_invalid_codepoints.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_2_invalid_codepoints.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_2_invalid_codepoints.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_3_escaped_invalid_codepoints.json b/formats/json-tests/jvmTest/resources/corner_cases/string_3_escaped_invalid_codepoints.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_3_escaped_invalid_codepoints.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_3_escaped_invalid_codepoints.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_3_invalid_codepoints.json b/formats/json-tests/jvmTest/resources/corner_cases/string_3_invalid_codepoints.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_3_invalid_codepoints.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_3_invalid_codepoints.json diff --git a/formats/json/jvmTest/resources/corner_cases/string_with_escaped_NULL.json b/formats/json-tests/jvmTest/resources/corner_cases/string_with_escaped_NULL.json similarity index 100% rename from formats/json/jvmTest/resources/corner_cases/string_with_escaped_NULL.json rename to formats/json-tests/jvmTest/resources/corner_cases/string_with_escaped_NULL.json diff --git a/formats/json/jvmTest/resources/corpus.zip b/formats/json-tests/jvmTest/resources/corpus.zip similarity index 100% rename from formats/json/jvmTest/resources/corpus.zip rename to formats/json-tests/jvmTest/resources/corpus.zip diff --git a/formats/json/jvmTest/resources/spec_cases/listing.txt b/formats/json-tests/jvmTest/resources/spec_cases/listing.txt similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/listing.txt rename to formats/json-tests/jvmTest/resources/spec_cases/listing.txt diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_1_true_without_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_1_true_without_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_1_true_without_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_1_true_without_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_a_invalid_utf8.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_a_invalid_utf8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_a_invalid_utf8.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_a_invalid_utf8.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_colon_instead_of_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_colon_instead_of_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_colon_instead_of_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_colon_instead_of_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_comma_after_close.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_comma_after_close.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_comma_after_close.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_comma_after_close.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_comma_and_number.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_comma_and_number.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_comma_and_number.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_comma_and_number.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_double_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_double_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_double_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_double_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_double_extra_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_double_extra_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_double_extra_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_double_extra_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_extra_close.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_extra_close.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_extra_close.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_extra_close.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_extra_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_extra_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_extra_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_extra_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_incomplete.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_incomplete.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_incomplete.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_incomplete.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_incomplete_invalid_value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_incomplete_invalid_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_incomplete_invalid_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_incomplete_invalid_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_inner_array_no_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_inner_array_no_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_inner_array_no_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_inner_array_no_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_invalid_utf8.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_invalid_utf8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_invalid_utf8.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_invalid_utf8.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_items_separated_by_semicolon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_items_separated_by_semicolon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_items_separated_by_semicolon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_items_separated_by_semicolon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_just_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_just_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_just_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_just_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_just_minus.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_just_minus.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_just_minus.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_just_minus.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_missing_value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_missing_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_missing_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_missing_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_newlines_unclosed.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_newlines_unclosed.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_newlines_unclosed.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_newlines_unclosed.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_number_and_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_number_and_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_number_and_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_number_and_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_number_and_several_commas.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_number_and_several_commas.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_number_and_several_commas.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_number_and_several_commas.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_spaces_vertical_tab_formfeed.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_spaces_vertical_tab_formfeed.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_spaces_vertical_tab_formfeed.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_spaces_vertical_tab_formfeed.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_star_inside.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_star_inside.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_star_inside.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_star_inside.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_unclosed.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_unclosed.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_unclosed_trailing_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_trailing_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_unclosed_trailing_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_trailing_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_unclosed_with_new_lines.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_with_new_lines.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_unclosed_with_new_lines.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_with_new_lines.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_array_unclosed_with_object_inside.json b/formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_with_object_inside.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_array_unclosed_with_object_inside.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_array_unclosed_with_object_inside.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_incomplete_false.json b/formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_false.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_incomplete_false.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_false.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_incomplete_null.json b/formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_incomplete_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_incomplete_true.json b/formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_true.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_incomplete_true.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_incomplete_true.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_multidigit_number_then_00.json b/formats/json-tests/jvmTest/resources/spec_cases/n_multidigit_number_then_00.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_multidigit_number_then_00.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_multidigit_number_then_00.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_bad_value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_bad_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_bad_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_bad_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_bracket_key.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_bracket_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_bracket_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_bracket_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_comma_instead_of_colon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_comma_instead_of_colon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_comma_instead_of_colon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_comma_instead_of_colon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_double_colon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_double_colon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_double_colon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_double_colon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_emoji.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_emoji.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_emoji.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_emoji.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_garbage_at_end.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_garbage_at_end.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_garbage_at_end.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_garbage_at_end.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_key_with_single_quotes.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_key_with_single_quotes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_key_with_single_quotes.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_key_with_single_quotes.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_lone_continuation_byte_in_key_and_trailing_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_lone_continuation_byte_in_key_and_trailing_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_lone_continuation_byte_in_key_and_trailing_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_lone_continuation_byte_in_key_and_trailing_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_missing_colon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_colon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_missing_colon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_colon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_missing_key.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_missing_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_missing_semicolon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_semicolon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_missing_semicolon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_semicolon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_missing_value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_missing_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_missing_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_no-colon.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_no-colon.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_no-colon.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_no-colon.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_non_string_key.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_non_string_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_non_string_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_non_string_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_non_string_key_but_huge_number_instead.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_non_string_key_but_huge_number_instead.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_non_string_key_but_huge_number_instead.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_non_string_key_but_huge_number_instead.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_repeated_null_null.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_repeated_null_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_repeated_null_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_repeated_null_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_several_trailing_commas.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_several_trailing_commas.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_several_trailing_commas.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_several_trailing_commas.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_single_quote.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_single_quote.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_single_quote.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_single_quote.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_trailing_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_trailing_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_open.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_open.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_open.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_open.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open_incomplete.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open_incomplete.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open_incomplete.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open_incomplete.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_two_commas_in_a_row.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_two_commas_in_a_row.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_two_commas_in_a_row.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_two_commas_in_a_row.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_unquoted_key.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_unquoted_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_unquoted_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_unquoted_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_unterminated-value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_unterminated-value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_unterminated-value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_unterminated-value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_with_single_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_with_single_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_with_single_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_with_single_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_object_with_trailing_garbage.json b/formats/json-tests/jvmTest/resources/spec_cases/n_object_with_trailing_garbage.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_object_with_trailing_garbage.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_object_with_trailing_garbage.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_single_space.json b/formats/json-tests/jvmTest/resources/spec_cases/n_single_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_single_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_single_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1x.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1x.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1x.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1x.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_accentuated_char_no_quotes.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_accentuated_char_no_quotes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_accentuated_char_no_quotes.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_accentuated_char_no_quotes.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_backslash_00.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_backslash_00.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_backslash_00.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_backslash_00.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_escape_x.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_escape_x.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_escape_x.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_escape_x.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_escaped_backslash_bad.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_backslash_bad.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_escaped_backslash_bad.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_backslash_bad.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_escaped_ctrl_char_tab.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_ctrl_char_tab.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_escaped_ctrl_char_tab.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_ctrl_char_tab.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_escaped_emoji.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_emoji.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_escaped_emoji.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_escaped_emoji.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_incomplete_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_incomplete_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_incomplete_escaped_character.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_escaped_character.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_incomplete_escaped_character.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_escaped_character.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_incomplete_surrogate.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_surrogate.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_incomplete_surrogate.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_surrogate.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_incomplete_surrogate_escape_invalid.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_surrogate_escape_invalid.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_incomplete_surrogate_escape_invalid.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_incomplete_surrogate_escape_invalid.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_invalid-utf-8-in-escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid-utf-8-in-escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_invalid-utf-8-in-escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid-utf-8-in-escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_invalid_backslash_esc.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_backslash_esc.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_invalid_backslash_esc.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_backslash_esc.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_invalid_unicode_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_unicode_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_invalid_unicode_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_unicode_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_invalid_utf8_after_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_utf8_after_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_invalid_utf8_after_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_invalid_utf8_after_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_leading_uescaped_thinspace.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_leading_uescaped_thinspace.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_leading_uescaped_thinspace.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_leading_uescaped_thinspace.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_no_quotes_with_bad_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_no_quotes_with_bad_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_no_quotes_with_bad_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_no_quotes_with_bad_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_single_doublequote.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_single_doublequote.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_single_doublequote.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_single_doublequote.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_single_quote.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_single_quote.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_single_quote.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_single_quote.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_single_string_no_double_quotes.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_single_string_no_double_quotes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_single_string_no_double_quotes.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_single_string_no_double_quotes.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_start_escape_unclosed.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_start_escape_unclosed.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_start_escape_unclosed.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_start_escape_unclosed.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_unescaped_crtl_char.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_crtl_char.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_unescaped_crtl_char.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_crtl_char.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_unescaped_newline.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_newline.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_unescaped_newline.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_newline.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_unescaped_tab.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_tab.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_unescaped_tab.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_unescaped_tab.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_unicode_CapitalU.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_unicode_CapitalU.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_unicode_CapitalU.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_unicode_CapitalU.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_string_with_trailing_garbage.json b/formats/json-tests/jvmTest/resources/spec_cases/n_string_with_trailing_garbage.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_string_with_trailing_garbage.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_string_with_trailing_garbage.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_100000_opening_arrays.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_100000_opening_arrays.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_100000_opening_arrays.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_100000_opening_arrays.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_U+2060_word_joined.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_U+2060_word_joined.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_U+2060_word_joined.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_U+2060_word_joined.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_UTF8_BOM_no_data.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_UTF8_BOM_no_data.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_UTF8_BOM_no_data.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_UTF8_BOM_no_data.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_angle_bracket_..json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_angle_bracket_..json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_angle_bracket_..json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_angle_bracket_..json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_angle_bracket_null.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_angle_bracket_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_angle_bracket_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_angle_bracket_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_array_trailing_garbage.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_trailing_garbage.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_array_trailing_garbage.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_trailing_garbage.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_array_with_extra_array_close.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_with_extra_array_close.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_array_with_extra_array_close.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_with_extra_array_close.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_array_with_unclosed_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_with_unclosed_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_array_with_unclosed_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_array_with_unclosed_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_ascii-unicode-identifier.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_ascii-unicode-identifier.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_ascii-unicode-identifier.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_ascii-unicode-identifier.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_capitalized_True.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_capitalized_True.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_capitalized_True.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_capitalized_True.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_close_unopened_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_close_unopened_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_close_unopened_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_close_unopened_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_comma_instead_of_closing_brace.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_comma_instead_of_closing_brace.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_comma_instead_of_closing_brace.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_comma_instead_of_closing_brace.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_double_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_double_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_double_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_double_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_end_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_end_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_end_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_end_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_incomplete_UTF8_BOM.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_incomplete_UTF8_BOM.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_incomplete_UTF8_BOM.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_incomplete_UTF8_BOM.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_lone-invalid-utf-8.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_lone-invalid-utf-8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_lone-invalid-utf-8.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_lone-invalid-utf-8.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_lone-open-bracket.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_lone-open-bracket.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_lone-open-bracket.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_lone-open-bracket.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_no_data.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_no_data.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_no_data.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_no_data.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_null-byte-outside-string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_null-byte-outside-string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_null-byte-outside-string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_null-byte-outside-string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_number_with_trailing_garbage.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_number_with_trailing_garbage.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_number_with_trailing_garbage.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_number_with_trailing_garbage.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_object_followed_by_closing_object.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_followed_by_closing_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_object_followed_by_closing_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_followed_by_closing_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_object_unclosed_no_value.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_unclosed_no_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_object_unclosed_no_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_unclosed_no_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_object_with_comment.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_with_comment.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_object_with_comment.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_with_comment.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_object_with_trailing_garbage.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_with_trailing_garbage.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_object_with_trailing_garbage.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_object_with_trailing_garbage.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_apostrophe.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_apostrophe.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_apostrophe.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_apostrophe.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_object.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_open_object.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_open_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_open_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_open_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_open_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_open_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_open_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_open_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_array_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_array_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_array_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object_close_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_close_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object_close_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_close_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object_comma.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_comma.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object_comma.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_comma.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object_open_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_open_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object_open_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_open_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object_open_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_open_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object_open_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_open_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_object_string_with_apostrophes.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_string_with_apostrophes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_object_string_with_apostrophes.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_object_string_with_apostrophes.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_open_open.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_open.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_open_open.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_open_open.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_single_star.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_single_star.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_single_star.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_single_star.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_trailing_#.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_trailing_#.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_trailing_#.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_trailing_#.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_uescaped_LF_before_string.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_uescaped_LF_before_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_uescaped_LF_before_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_uescaped_LF_before_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_partial_null.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_partial_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_partial_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_partial_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_false.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_false.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_false.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_false.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_true.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_true.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_true.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_true.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_object.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unclosed_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unclosed_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_unicode-identifier.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_unicode-identifier.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_unicode-identifier.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_unicode-identifier.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_whitespace_U+2060_word_joiner.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_whitespace_U+2060_word_joiner.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_whitespace_U+2060_word_joiner.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_whitespace_U+2060_word_joiner.json diff --git a/formats/json/jvmTest/resources/spec_cases/n_structure_whitespace_formfeed.json b/formats/json-tests/jvmTest/resources/spec_cases/n_structure_whitespace_formfeed.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/n_structure_whitespace_formfeed.json rename to formats/json-tests/jvmTest/resources/spec_cases/n_structure_whitespace_formfeed.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_arraysWithSpaces.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_arraysWithSpaces.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_arraysWithSpaces.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_arraysWithSpaces.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_empty-string.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_empty-string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_empty-string.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_empty-string.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_empty.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_empty.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_empty.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_empty.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_ending_with_newline.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_ending_with_newline.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_ending_with_newline.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_ending_with_newline.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_false.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_false.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_false.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_false.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_heterogeneous.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_heterogeneous.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_heterogeneous.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_heterogeneous.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_null.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_with_1_and_newline.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_with_1_and_newline.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_with_1_and_newline.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_with_1_and_newline.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_with_leading_space.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_with_leading_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_with_leading_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_with_leading_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_with_several_null.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_with_several_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_with_several_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_with_several_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_array_with_trailing_space.json b/formats/json-tests/jvmTest/resources/spec_cases/y_array_with_trailing_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_array_with_trailing_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_array_with_trailing_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_0e+1.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_0e+1.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_0e+1.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_0e+1.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_0e1.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_0e1.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_0e1.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_0e1.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_after_space.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_after_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_after_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_after_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_double_close_to_zero.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_double_close_to_zero.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_double_close_to_zero.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_double_close_to_zero.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_int_with_exp.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_int_with_exp.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_int_with_exp.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_int_with_exp.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_minus_zero.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_minus_zero.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_minus_zero.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_minus_zero.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_negative_int.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_int.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_negative_int.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_int.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_negative_one.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_one.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_negative_one.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_one.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_negative_zero.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_zero.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_negative_zero.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_negative_zero.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e_neg_exp.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e_neg_exp.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e_neg_exp.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e_neg_exp.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e_pos_exp.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e_pos_exp.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_capital_e_pos_exp.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_capital_e_pos_exp.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_exponent.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_exponent.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_exponent.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_exponent.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_fraction_exponent.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_fraction_exponent.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_fraction_exponent.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_fraction_exponent.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_neg_exp.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_neg_exp.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_neg_exp.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_neg_exp.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_real_pos_exponent.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_real_pos_exponent.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_real_pos_exponent.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_real_pos_exponent.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_simple_int.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_simple_int.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_simple_int.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_simple_int.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_number_simple_real.json b/formats/json-tests/jvmTest/resources/spec_cases/y_number_simple_real.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_number_simple_real.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_number_simple_real.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_basic.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_basic.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_basic.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_basic.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_duplicated_key.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_duplicated_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_duplicated_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_duplicated_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_duplicated_key_and_value.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_duplicated_key_and_value.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_duplicated_key_and_value.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_duplicated_key_and_value.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_empty.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_empty.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_empty.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_empty.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_empty_key.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_empty_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_empty_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_empty_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_escaped_null_in_key.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_escaped_null_in_key.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_escaped_null_in_key.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_escaped_null_in_key.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_extreme_numbers.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_extreme_numbers.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_extreme_numbers.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_extreme_numbers.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_long_strings.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_long_strings.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_long_strings.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_long_strings.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_simple.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_simple.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_simple.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_simple.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_string_unicode.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_string_unicode.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_string_unicode.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_string_unicode.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_object_with_newlines.json b/formats/json-tests/jvmTest/resources/spec_cases/y_object_with_newlines.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_object_with_newlines.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_object_with_newlines.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_1_2_3_bytes_UTF-8_sequences.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_1_2_3_bytes_UTF-8_sequences.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_1_2_3_bytes_UTF-8_sequences.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_1_2_3_bytes_UTF-8_sequences.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pair.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pair.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pair.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pair.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pairs.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pairs.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pairs.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pairs.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_allowed_escapes.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_allowed_escapes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_allowed_escapes.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_allowed_escapes.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_backslash_and_u_escaped_zero.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_backslash_and_u_escaped_zero.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_backslash_and_u_escaped_zero.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_backslash_and_u_escaped_zero.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_backslash_doublequotes.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_backslash_doublequotes.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_backslash_doublequotes.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_backslash_doublequotes.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_comments.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_comments.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_comments.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_comments.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_double_escape_a.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_double_escape_a.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_double_escape_a.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_double_escape_a.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_double_escape_n.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_double_escape_n.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_double_escape_n.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_double_escape_n.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_escaped_control_character.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_escaped_control_character.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_escaped_control_character.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_escaped_control_character.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_escaped_noncharacter.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_escaped_noncharacter.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_escaped_noncharacter.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_escaped_noncharacter.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_in_array.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_in_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_in_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_in_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_in_array_with_leading_space.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_in_array_with_leading_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_in_array_with_leading_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_in_array_with_leading_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_last_surrogates_1_and_2.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_last_surrogates_1_and_2.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_last_surrogates_1_and_2.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_last_surrogates_1_and_2.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_nbsp_uescaped.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_nbsp_uescaped.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_nbsp_uescaped.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_nbsp_uescaped.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+10FFFF.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+10FFFF.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+10FFFF.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+10FFFF.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+FFFF.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+FFFF.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+FFFF.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+FFFF.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_null_escape.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_null_escape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_null_escape.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_null_escape.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_one-byte-utf-8.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_one-byte-utf-8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_one-byte-utf-8.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_one-byte-utf-8.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_pi.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_pi.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_pi.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_pi.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_reservedCharacterInUTF-8_U+1BFFF.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_reservedCharacterInUTF-8_U+1BFFF.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_reservedCharacterInUTF-8_U+1BFFF.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_reservedCharacterInUTF-8_U+1BFFF.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_simple_ascii.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_simple_ascii.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_simple_ascii.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_simple_ascii.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_space.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_space.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_space.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_space.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_three-byte-utf-8.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_three-byte-utf-8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_three-byte-utf-8.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_three-byte-utf-8.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_two-byte-utf-8.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_two-byte-utf-8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_two-byte-utf-8.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_two-byte-utf-8.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_u+2028_line_sep.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_u+2028_line_sep.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_u+2028_line_sep.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_u+2028_line_sep.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_u+2029_par_sep.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_u+2029_par_sep.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_u+2029_par_sep.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_u+2029_par_sep.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_uEscape.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_uEscape.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_uEscape.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_uEscape.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_uescaped_newline.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_uescaped_newline.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_uescaped_newline.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_uescaped_newline.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unescaped_char_delete.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unescaped_char_delete.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unescaped_char_delete.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unescaped_char_delete.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicodeEscapedBackslash.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicodeEscapedBackslash.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicodeEscapedBackslash.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicodeEscapedBackslash.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_2.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_2.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_2.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_2.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+10FFFE_nonchar.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+10FFFE_nonchar.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+10FFFE_nonchar.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+10FFFE_nonchar.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+1FFFE_nonchar.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+1FFFE_nonchar.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+1FFFE_nonchar.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+1FFFE_nonchar.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+2064_invisible_plus.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+2064_invisible_plus.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+2064_invisible_plus.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+2064_invisible_plus.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+FDD0_nonchar.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+FDD0_nonchar.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+FDD0_nonchar.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+FDD0_nonchar.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+FFFE_nonchar.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+FFFE_nonchar.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_U+FFFE_nonchar.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_U+FFFE_nonchar.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_unicode_escaped_double_quote.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_escaped_double_quote.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_unicode_escaped_double_quote.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_unicode_escaped_double_quote.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_utf8.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_utf8.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_utf8.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_utf8.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_string_with_del_character.json b/formats/json-tests/jvmTest/resources/spec_cases/y_string_with_del_character.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_string_with_del_character.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_string_with_del_character.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_false.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_false.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_false.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_false.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_int.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_int.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_int.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_int.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_negative_real.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_negative_real.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_negative_real.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_negative_real.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_null.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_null.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_null.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_null.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_string.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_string.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_string.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_string.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_lonely_true.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_true.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_lonely_true.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_lonely_true.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_string_empty.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_string_empty.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_string_empty.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_string_empty.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_trailing_newline.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_trailing_newline.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_trailing_newline.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_trailing_newline.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_true_in_array.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_true_in_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_true_in_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_true_in_array.json diff --git a/formats/json/jvmTest/resources/spec_cases/y_structure_whitespace_array.json b/formats/json-tests/jvmTest/resources/spec_cases/y_structure_whitespace_array.json similarity index 100% rename from formats/json/jvmTest/resources/spec_cases/y_structure_whitespace_array.json rename to formats/json-tests/jvmTest/resources/spec_cases/y_structure_whitespace_array.json diff --git a/formats/json/jvmTest/src/kotlinx/serialization/JavaCollectionsTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/JavaCollectionsTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/JavaCollectionsTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/JavaCollectionsTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt similarity index 99% rename from formats/json/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt index b932b5aee..5fc366a9e 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt @@ -5,7 +5,6 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.polymorphic import kotlinx.serialization.modules.subclass -import org.junit.Ignore import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertTrue diff --git a/formats/json/jvmTest/src/kotlinx/serialization/SerializationCasesTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/SerializationCasesTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/SerializationCasesTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/SerializationCasesTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt similarity index 98% rename from formats/json/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt index db79b4779..3d634fcaf 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt @@ -4,7 +4,6 @@ package kotlinx.serialization -import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlinx.serialization.json.Json diff --git a/formats/json/jvmTest/src/kotlinx/serialization/SerializerForNullableJavaTypeTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/SerializerForNullableJavaTypeTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/SerializerForNullableJavaTypeTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/SerializerForNullableJavaTypeTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt similarity index 76% rename from formats/json/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt index ca285d250..e0df42209 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt @@ -22,12 +22,12 @@ class StacktraceRecoveryTest { } @Test - fun testJsonDecodingException() = checkRecovered { + fun testJsonDecodingException() = checkRecovered("JsonDecodingException") { Json.decodeFromString("42") } @Test - fun testJsonEncodingException() = checkRecovered { + fun testJsonEncodingException() = checkRecovered("JsonEncodingException") { Json.encodeToString(Double.NaN) } @@ -57,19 +57,6 @@ class StacktraceRecoveryTest { assertEquals(exceptionClassSimpleName, e::class.simpleName!!) } - private inline fun checkRecovered(noinline block: () -> Unit) = runBlocking { - val result = runCatching { - callBlockWithRecovery(block) - } - assertTrue(result.isFailure, "Block should have failed") - val e = result.exceptionOrNull()!! - assertEquals(E::class, e::class) - val cause = e.cause - assertNotNull(cause, "Exception should have cause: $e") - assertEquals(e.message, cause.message) - assertEquals(E::class, cause::class) - } - // KLUDGE: A separate function with state-machine to ensure coroutine DebugMetadata is generated. See KT-41789 private suspend fun callBlockWithRecovery(block: () -> Unit) { yield() diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/ContextualSerializationOnFileTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/ContextualSerializationOnFileTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/features/ContextualSerializationOnFileTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/ContextualSerializationOnFileTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/InternalInheritanceTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/InternalInheritanceTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/features/InternalInheritanceTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/InternalInheritanceTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt similarity index 97% rename from formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt index 0de89d9c5..7019edae4 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt @@ -1,7 +1,9 @@ /* - * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") + package kotlinx.serialization.features import kotlinx.serialization.* diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt similarity index 95% rename from formats/json/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt index aad9a0f51..f6d13f702 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt @@ -12,8 +12,8 @@ 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 +import kotlinx.serialization.test.assertFailsWithSerial import org.junit.Test import java.io.* import kotlin.test.* @@ -142,7 +142,7 @@ class JsonLazySequenceTest { val input2 = """[1, 2, 3]qwert""" val input3 = """[1,2 3]""" withInputs(input1, input2, input3) { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { json.decodeToSequence(it, Int.serializer()).toList() } } @@ -151,13 +151,13 @@ class JsonLazySequenceTest { @Test fun testMultilineArrays() { val input = "[1,2,3]\n[4,5,6]\n[7,8,9]" - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { json.decodeToSequence>(input.asInputStream(), DecodeSequenceMode.AUTO_DETECT).toList() } - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { json.decodeToSequence(input.asInputStream(), DecodeSequenceMode.AUTO_DETECT).toList() } - assertFailsWith { // we do not merge lists + assertFailsWithSerial("JsonDecodingException") { // we do not merge lists json.decodeToSequence(input.asInputStream(), DecodeSequenceMode.ARRAY_WRAPPED).toList() } val parsed = json.decodeToSequence>(input.asInputStream(), DecodeSequenceMode.WHITESPACE_SEPARATED).toList() @@ -167,7 +167,7 @@ class JsonLazySequenceTest { @Test fun testStrictArrayCheck() { - assertFailsWith { + assertFailsWithSerial("JsonDecodingException") { json.decodeToSequence(inputStringWsSeparated.asInputStream(), DecodeSequenceMode.ARRAY_WRAPPED) } } diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt similarity index 73% rename from formats/json/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt index 287e44388..397caffdf 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt @@ -4,20 +4,12 @@ package kotlinx.serialization.features -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.runBlocking import kotlinx.serialization.* import kotlinx.serialization.Serializable -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 import org.junit.Test import java.io.* -import kotlin.test.* class JsonSequencePathTest { diff --git a/formats/json/jvmTest/src/kotlinx/serialization/features/SerializerByTypeTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/SerializerByTypeTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/features/SerializerByTypeTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/SerializerByTypeTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/json/GsonCompatibilityTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/json/GsonCompatibilityTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/json/GsonCompatibilityTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/json/GsonCompatibilityTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/json/ParallelJsonStressTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/json/ParallelJsonStressTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/json/ParallelJsonStressTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/json/ParallelJsonStressTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/json/SpecConformanceTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/json/SpecConformanceTest.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/json/SpecConformanceTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/json/SpecConformanceTest.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/test/CurrentPlatform.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/test/CurrentPlatform.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/test/CurrentPlatform.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/test/CurrentPlatform.kt diff --git a/formats/json/jvmTest/src/kotlinx/serialization/test/JsonHelpers.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/test/JsonHelpers.kt similarity index 100% rename from formats/json/jvmTest/src/kotlinx/serialization/test/JsonHelpers.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/test/JsonHelpers.kt diff --git a/formats/json/nativeTest/src/kotlinx/serialization/json/MultiWorkerJsonTest.kt b/formats/json-tests/nativeTest/src/kotlinx/serialization/json/MultiWorkerJsonTest.kt similarity index 100% rename from formats/json/nativeTest/src/kotlinx/serialization/json/MultiWorkerJsonTest.kt rename to formats/json-tests/nativeTest/src/kotlinx/serialization/json/MultiWorkerJsonTest.kt diff --git a/formats/json/nativeTest/src/kotlinx/serialization/test/CurrentPlatform.kt b/formats/json-tests/nativeTest/src/kotlinx/serialization/test/CurrentPlatform.kt similarity index 100% rename from formats/json/nativeTest/src/kotlinx/serialization/test/CurrentPlatform.kt rename to formats/json-tests/nativeTest/src/kotlinx/serialization/test/CurrentPlatform.kt diff --git a/formats/json/nativeTest/src/kotlinx/serialization/test/JsonHelpers.kt b/formats/json-tests/nativeTest/src/kotlinx/serialization/test/JsonHelpers.kt similarity index 100% rename from formats/json/nativeTest/src/kotlinx/serialization/test/JsonHelpers.kt rename to formats/json-tests/nativeTest/src/kotlinx/serialization/test/JsonHelpers.kt diff --git a/formats/json/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index cb5aaeb3e..bdfbe731f 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -358,3 +358,34 @@ public final class kotlinx/serialization/json/JvmStreamsKt { public static final fun encodeToStream (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Ljava/io/OutputStream;)V } +public final class kotlinx/serialization/json/internal/JsonStreamsKt { + public static final fun decodeByReader (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/internal/SerialReader;)Ljava/lang/Object; + public static final fun decodeToSequenceByReader (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/SerialReader;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeToSequenceByReader$default (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/SerialReader;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; + public static final fun encodeByWriter (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/JsonWriter;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V +} + +public abstract interface class kotlinx/serialization/json/internal/JsonWriter { + public abstract fun release ()V + public abstract fun write (Ljava/lang/String;)V + public abstract fun writeChar (C)V + public abstract fun writeLong (J)V + public abstract fun writeQuoted (Ljava/lang/String;)V +} + +public abstract interface class kotlinx/serialization/json/internal/SerialReader { + public abstract fun read ([CII)I +} + +public final class kotlinx/serialization/json/internal/StreamingJsonDecoderKt { + public static final fun decodeStringToJsonTree (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Ljava/lang/String;)Lkotlinx/serialization/json/JsonElement; +} + +public final class kotlinx/serialization/json/internal/TreeJsonDecoderKt { + public static final fun readJson (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/JsonElement;Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object; +} + +public final class kotlinx/serialization/json/internal/TreeJsonEncoderKt { + public static final fun writeJson (Lkotlinx/serialization/json/Json;Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Lkotlinx/serialization/json/JsonElement; +} + diff --git a/formats/json/build.gradle b/formats/json/build.gradle index 229444598..8f2b5af7b 100644 --- a/formats/json/build.gradle +++ b/formats/json/build.gradle @@ -7,6 +7,17 @@ apply plugin: 'kotlinx-serialization' apply from: rootProject.file("gradle/native-targets.gradle") apply from: rootProject.file("gradle/configure-source-sets.gradle") +// disable kover tasks because there are no tests in the project +tasks.named("koverHtmlReport") { + enabled = false +} +tasks.named("koverXmlReport") { + enabled = false +} +tasks.named("koverVerify") { + enabled = false +} + kotlin { sourceSets { @@ -15,18 +26,7 @@ kotlin { api project(":kotlinx-serialization-core") } } - - jvmTest { - dependencies { - implementation 'com.google.code.gson:gson:2.8.5' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - } - } } } -compileTestKotlinJsLegacy { - exclude '**/PropertyInitializerTest.kt' -} - Java9Modularity.configureJava9ModuleInfo(project) diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt b/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt index 8f1f02fd6..abb9b4bc9 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt @@ -75,14 +75,9 @@ public sealed class Json( * @throws [SerializationException] if the given value cannot be serialized to JSON. */ public final override fun encodeToString(serializer: SerializationStrategy, value: T): String { - val result = JsonStringBuilder() + val result = JsonToStringWriter() try { - val encoder = StreamingJsonEncoder( - result, this, - WriteMode.OBJ, - arrayOfNulls(WriteMode.values().size) - ) - encoder.encodeSerializableValue(serializer, value) + encodeByWriter(result, serializer, value) return result.toString() } finally { result.release() @@ -129,6 +124,60 @@ public sealed class Json( } } +/** + * Description of JSON input shape used for decoding to sequence. + * + * The sequence represents a stream of objects parsed one by one; + * [DecodeSequenceMode] defines a separator between these objects. + * Typically, these objects are not separated by meaningful characters ([WHITESPACE_SEPARATED]), + * or the whole stream is a large array of objects separated with commas ([ARRAY_WRAPPED]). + */ +@ExperimentalSerializationApi +public enum class DecodeSequenceMode { + /** + * Declares that objects in the input stream are separated by whitespace characters. + * + * The stream is read as multiple JSON objects separated by any number of whitespace characters between objects. Starting and trailing whitespace characters are also permitted. + * Each individual object is parsed lazily, when it is requested from the resulting sequence. + * + * Whitespace character is either ' ', '\n', '\r' or '\t'. + * + * Example of `WHITESPACE_SEPARATED` stream content: + * ``` + * """{"key": "value"}{"key": "value2"} {"key2": "value2"}""" + * ``` + */ + WHITESPACE_SEPARATED, + + /** + * Declares that objects in the input stream are wrapped in the JSON array. + * Each individual object in the array is parsed lazily when it is requested from the resulting sequence. + * + * The stream is read as multiple JSON objects wrapped into a JSON array. + * The stream must start with an array start character `[` and end with an array end character `]`, + * otherwise, [JsonDecodingException] is thrown. + * + * Example of `ARRAY_WRAPPED` stream content: + * ``` + * """[{"key": "value"}, {"key": "value2"},{"key2": "value2"}]""" + * ``` + */ + ARRAY_WRAPPED, + + /** + * Declares that parser itself should select between [WHITESPACE_SEPARATED] and [ARRAY_WRAPPED] modes. + * The selection is performed by looking on the first meaningful character of the stream. + * + * In most cases, auto-detection is sufficient to correctly parse an input. + * If the input is _whitespace-separated stream of the arrays_, parser could select an incorrect mode, + * for that [DecodeSequenceMode] must be specified explicitly. + * + * Example of an exceptional case: + * `[1, 2, 3] [4, 5, 6]\n[7, 8, 9]` + */ + AUTO_DETECT; +} + /** * Creates an instance of [Json] configured from the optionally given [Json instance][from] and adjusted with [builderAction]. */ 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 553d6358e..5089955a9 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/Composers.kt @@ -9,11 +9,11 @@ import kotlinx.serialization.* import kotlinx.serialization.json.* import kotlin.jvm.* -internal fun Composer(sb: JsonStringBuilder, json: Json): Composer = +internal fun Composer(sb: JsonWriter, json: Json): Composer = if (json.configuration.prettyPrint) ComposerWithPrettyPrint(sb, json) else Composer(sb) @OptIn(ExperimentalSerializationApi::class) -internal open class Composer(@JvmField internal val sb: JsonStringBuilder) { +internal open class Composer(@JvmField internal val writer: JsonWriter) { var writingFirst = true protected set @@ -29,19 +29,19 @@ internal open class Composer(@JvmField internal val sb: JsonStringBuilder) { open fun space() = Unit - fun print(v: Char) = sb.append(v) - fun print(v: String) = sb.append(v) - open fun print(v: Float) = sb.append(v.toString()) - open fun print(v: Double) = sb.append(v.toString()) - open fun print(v: Byte) = sb.append(v.toLong()) - open fun print(v: Short) = sb.append(v.toLong()) - open fun print(v: Int) = sb.append(v.toLong()) - open fun print(v: Long) = sb.append(v) - open fun print(v: Boolean) = sb.append(v.toString()) - fun printQuoted(value: String): Unit = sb.appendQuoted(value) + fun print(v: Char) = writer.writeChar(v) + fun print(v: String) = writer.write(v) + open fun print(v: Float) = writer.write(v.toString()) + open fun print(v: Double) = writer.write(v.toString()) + open fun print(v: Byte) = writer.writeLong(v.toLong()) + open fun print(v: Short) = writer.writeLong(v.toLong()) + open fun print(v: Int) = writer.writeLong(v.toLong()) + open fun print(v: Long) = writer.writeLong(v) + open fun print(v: Boolean) = writer.write(v.toString()) + fun printQuoted(value: String) = writer.writeQuoted(value) } -internal class ComposerForUnsignedNumbers(sb: JsonStringBuilder, private val forceQuoting: Boolean) : Composer(sb) { +internal class ComposerForUnsignedNumbers(writer: JsonWriter, private val forceQuoting: Boolean) : Composer(writer) { override fun print(v: Int) { if (forceQuoting) printQuoted(v.toUInt().toString()) else print(v.toUInt().toString()) } @@ -60,9 +60,9 @@ internal class ComposerForUnsignedNumbers(sb: JsonStringBuilder, private val for } internal class ComposerWithPrettyPrint( - sb: JsonStringBuilder, + writer: JsonWriter, private val json: Json -) : Composer(sb) { +) : Composer(writer) { private var level = 0 override fun indent() { diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonIterator.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonIterator.kt similarity index 100% rename from formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonIterator.kt rename to formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonIterator.kt diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt new file mode 100644 index 000000000..757032495 --- /dev/null +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt @@ -0,0 +1,65 @@ +package kotlinx.serialization.json.internal + +import kotlinx.serialization.* +import kotlinx.serialization.json.DecodeSequenceMode +import kotlinx.serialization.json.Json + + + +@InternalSerializationApi +public interface JsonWriter { + public fun writeLong(value: Long) + public fun writeChar(char: Char) + + public fun write(text: String) + + public fun writeQuoted(text: String) + + public fun release() +} + +@InternalSerializationApi +public interface SerialReader { + public fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int +} + +@InternalSerializationApi +public fun Json.encodeByWriter(writer: JsonWriter, serializer: SerializationStrategy, value: T) { + val encoder = StreamingJsonEncoder( + writer, this, + WriteMode.OBJ, + arrayOfNulls(WriteMode.values().size) + ) + encoder.encodeSerializableValue(serializer, value) +} + +@InternalSerializationApi +public fun Json.decodeByReader( + deserializer: DeserializationStrategy, + reader: SerialReader +): T { + val lexer = ReaderJsonLexer(reader) + val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor, null) + val result = input.decodeSerializableValue(deserializer) + lexer.expectEof() + return result +} + +@InternalSerializationApi +@ExperimentalSerializationApi +public fun Json.decodeToSequenceByReader( + reader: SerialReader, + deserializer: DeserializationStrategy, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence { + val lexer = ReaderJsonLexer(reader) + val iter = JsonIterator(format, this, lexer, deserializer) + return Sequence { iter }.constrainOnce() +} + +@InternalSerializationApi +@ExperimentalSerializationApi +public inline fun Json.decodeToSequenceByReader( + reader: SerialReader, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence = decodeToSequenceByReader(reader, serializersModule.serializer(), format) diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt deleted file mode 100644 index f9245d584..000000000 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt +++ /dev/null @@ -1,10 +0,0 @@ -package kotlinx.serialization.json.internal - -internal expect class JsonStringBuilder constructor() { - fun append(value: Long) - fun append(ch: Char) - fun append(string: String) - fun appendQuoted(string: String) - override fun toString(): String - fun release() -} diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt new file mode 100644 index 000000000..4df35def7 --- /dev/null +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt @@ -0,0 +1,10 @@ +package kotlinx.serialization.json.internal + +internal expect class JsonToStringWriter constructor() : JsonWriter { + override fun writeChar(char: Char) + override fun writeLong(value: Long) + override fun write(text: String) + override fun writeQuoted(text: String) + override fun toString(): String + override fun release() +} diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt index 834e59770..3505a9c5f 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt @@ -353,6 +353,18 @@ internal open class StreamingJsonDecoder( } } +@InternalSerializationApi +public fun Json.decodeStringToJsonTree( + deserializer: DeserializationStrategy, + source: String +): JsonElement { + val lexer = StringJsonLexer(source) + val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor, null) + val tree = input.decodeJsonElement() + lexer.expectEof() + return tree +} + @OptIn(ExperimentalSerializationApi::class) internal class JsonDecoderForUnsignedTypes( private val lexer: AbstractJsonLexer, 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 0fe6371e5..dd7682fe2 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt @@ -32,7 +32,7 @@ internal class StreamingJsonEncoder( ) : JsonEncoder, AbstractEncoder() { internal constructor( - output: JsonStringBuilder, json: Json, mode: WriteMode, + output: JsonWriter, json: Json, mode: WriteMode, modeReuseCache: Array ) : this(Composer(output, json), json, mode, modeReuseCache) @@ -166,7 +166,7 @@ internal class StreamingJsonEncoder( // inside the composer, but not in the encoder (otherwise we'll get into `if (forceQuoting) encodeString(value.toString())` part // and unsigned numbers would be encoded incorrectly) return if (composer is ComposerForUnsignedNumbers) composer - else ComposerForUnsignedNumbers(composer.sb, forceQuoting) + else ComposerForUnsignedNumbers(composer.writer, forceQuoting) } override fun encodeNull() { @@ -197,7 +197,7 @@ internal class StreamingJsonEncoder( // First encode value, then check, to have a prettier error message if (forceQuoting) encodeString(value.toString()) else composer.print(value) if (!configuration.allowSpecialFloatingPointValues && !value.isFinite()) { - throw InvalidFloatingPointEncoded(value, composer.sb.toString()) + throw InvalidFloatingPointEncoded(value, composer.writer.toString()) } } @@ -205,7 +205,7 @@ internal class StreamingJsonEncoder( // First encode value, then check, to have a prettier error message if (forceQuoting) encodeString(value.toString()) else composer.print(value) if (!configuration.allowSpecialFloatingPointValues && !value.isFinite()) { - throw InvalidFloatingPointEncoded(value, composer.sb.toString()) + throw InvalidFloatingPointEncoded(value, composer.writer.toString()) } } diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt index 99aed338e..21bb8af9b 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt @@ -12,6 +12,7 @@ private fun toHexChar(i: Int) : Char { else (d - 10 + 'a'.code).toChar() } +@PublishedApi @SharedImmutable internal val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { for (c in 0..0x1f) { diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt index fd2831187..6541cb3b3 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonDecoder.kt @@ -15,7 +15,8 @@ import kotlinx.serialization.json.* import kotlinx.serialization.modules.* import kotlin.jvm.* -internal fun Json.readJson(element: JsonElement, deserializer: DeserializationStrategy): T { +@InternalSerializationApi +public fun Json.readJson(element: JsonElement, deserializer: DeserializationStrategy): T { val input = when (element) { is JsonObject -> JsonTreeDecoder(this, element) is JsonArray -> JsonTreeListDecoder(this, element) diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt index dfd4b2c05..7e4240a49 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/TreeJsonEncoder.kt @@ -14,7 +14,8 @@ import kotlinx.serialization.modules.* import kotlin.collections.set import kotlin.jvm.* -internal fun Json.writeJson(value: T, serializer: SerializationStrategy): JsonElement { +@InternalSerializationApi +public fun Json.writeJson(value: T, serializer: SerializationStrategy): JsonElement { lateinit var result: JsonElement val encoder = JsonTreeEncoder(this) { result = it } encoder.encodeSerializableValue(serializer, value) diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt similarity index 88% rename from formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt rename to formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt index 28ec2cfc3..e02364ee4 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt @@ -2,20 +2,14 @@ * 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 +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") -import java.io.* -import java.nio.charset.Charset +package kotlinx.serialization.json.internal -internal const val BATCH_SIZE = 16 * 1024 +@PublishedApi +internal const val BATCH_SIZE: Int = 16 * 1024 private const val DEFAULT_THRESHOLD = 128 - -// This size of buffered reader is very important here, because utf-8 decoding is slow. -// Jackson and Moshi are faster because they have specialized UTF-8 parser directly over InputStream -internal const val READER_BUF_SIZE = 16 * BATCH_SIZE - - /** * For some reason this hand-rolled implementation is faster than * fun ArrayAsSequence(s: CharArray): CharSequence = java.nio.CharBuffer.wrap(s, 0, length) @@ -26,18 +20,16 @@ private class ArrayAsSequence(private val source: CharArray) : CharSequence { override fun get(index: Int): Char = source[index] override fun subSequence(startIndex: Int, endIndex: Int): CharSequence { - return String(source, startIndex, endIndex - startIndex) + return source.concatToString(startIndex, endIndex) } } internal class ReaderJsonLexer( - private val reader: Reader, + private val reader: SerialReader, private var _source: CharArray = CharArray(BATCH_SIZE) ) : AbstractJsonLexer() { private var threshold: Int = DEFAULT_THRESHOLD // chars - constructor(i: InputStream, charset: Charset = Charsets.UTF_8) : this(i.reader(charset).buffered(READER_BUF_SIZE)) - override var source: CharSequence = ArrayAsSequence(_source) init { @@ -75,7 +67,7 @@ internal class ReaderJsonLexer( private fun preload(spaceLeft: Int) { val buffer = _source - System.arraycopy(buffer, currentPosition, buffer, 0, spaceLeft) + buffer.copyInto(buffer, 0, currentPosition, currentPosition + spaceLeft) var read = spaceLeft val sizeTotal = _source.size while (read != sizeTotal) { @@ -168,11 +160,11 @@ internal class ReaderJsonLexer( } override fun substring(startPos: Int, endPos: Int): String { - return String(_source, startPos, endPos - startPos) + return _source.concatToString(startPos, endPos) } override fun appendRange(fromIndex: Int, toIndex: Int) { - escapedString.append(_source, fromIndex, toIndex - fromIndex) + escapedString.appendRange(_source, fromIndex, toIndex) } // Can be carefully implemented but postponed for now diff --git a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt b/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt deleted file mode 100644 index 7a45c8dd6..000000000 --- a/formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package kotlinx.serialization.json.serializers - -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.* -import kotlinx.serialization.json.internal.* -import kotlinx.serialization.test.* -import kotlin.test.* - -class JsonObjectSerializerTest : JsonTestBase() { - - private val expected = """{"element":{"literal":1,"nullKey":null,"nested":{"another literal":"some value"},"\\. escaped":"\\. escaped","\n new line":"\n new line"}}""" - private val expectedTopLevel = """{"literal":1,"nullKey":null,"nested":{"another literal":"some value"},"\\. escaped":"\\. escaped","\n new line":"\n new line"}""" - - @Test - fun testJsonObject() = parametrizedTest(default) { - assertStringFormAndRestored(expected, JsonObjectWrapper(prebuiltJson()), JsonObjectWrapper.serializer()) - } - - @Test - fun testJsonObjectAsElement() = parametrizedTest(default) { - assertStringFormAndRestored(expected, JsonElementWrapper(prebuiltJson()), JsonElementWrapper.serializer()) - } - - @Test - fun testTopLevelJsonObject() = parametrizedTest (default) { - assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonObjectSerializer) - } - - @Test - fun testTopLevelJsonObjectAsElement() = parametrizedTest (default) { - assertStringFormAndRestored(expectedTopLevel, prebuiltJson(), JsonElementSerializer) - } - - @Test - fun testJsonObjectToString() { - val prebuiltJson = prebuiltJson() - val string = lenient.encodeToString(JsonElementSerializer, prebuiltJson) - assertEquals(string, prebuiltJson.toString()) - } - - @Test - fun testDocumentationSample() { - val string = Json.encodeToString(JsonElementSerializer, buildJsonObject { put("key", 1.0) }) - val literal = Json.decodeFromString(JsonElementSerializer, string) - assertEquals(JsonObject(mapOf("key" to JsonPrimitive(1.0))), literal) - } - - @Test - fun testMissingCommas() = parametrizedTest { jsonTestingMode -> - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{ \"1\": \"2\" \"3\":\"4\"}", jsonTestingMode) } - } - - @Test - fun testEmptyObject() = parametrizedTest { jsonTestingMode -> - assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObjectSerializer, "{}", jsonTestingMode)) - assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObjectSerializer, "{}", jsonTestingMode)) - assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObjectSerializer, "{\n\n}", jsonTestingMode)) - assertEquals(JsonObject(emptyMap()), lenient.decodeFromString(JsonObjectSerializer, "{ \t}", jsonTestingMode)) - } - - @Test - fun testInvalidObject() = parametrizedTest { jsonTestingMode -> - assertFailsWith { default.decodeFromString(JsonObjectSerializer, "{\"a\":\"b\"]", jsonTestingMode) } - assertFailsWith { default.decodeFromString(JsonObjectSerializer, "{", jsonTestingMode) } - if (jsonTestingMode != JsonTestingMode.JAVA_STREAMS) // Streams support dangling characters - assertFailsWith { default.decodeFromString(JsonObjectSerializer, "{}}", jsonTestingMode) } - assertFailsWith { default.decodeFromString(JsonObjectSerializer, "{]", jsonTestingMode) } - } - - @Test - fun testWhitespaces() = parametrizedTest { jsonTestingMode -> - assertEquals( - JsonObject(mapOf("1" to JsonPrimitive(2), "3" to JsonPrimitive(4), "5" to JsonPrimitive(6))), - lenient.decodeFromString(JsonObjectSerializer, "{1: 2, 3: \n 4, 5:6}", jsonTestingMode) - ) - } - - @Test - fun testExcessiveCommas() = parametrizedTest { jsonTestingMode -> - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{\"a\":\"b\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{\"a\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,\"1\":\"2\"}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,\"1\":\"2\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,,\"1\":\"2\"}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{\"1\":\"2\",,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{\"1\":\"2\",,\"2\":\"2\"}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{, ,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(JsonObjectSerializer, "{,\n,}", jsonTestingMode) } - } - - @Serializable - data class Holder(val a: String) - - @Test - fun testExcessiveCommasInObject() = parametrizedTest { jsonTestingMode -> - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{\"a\":\"b\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{\"a\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,\"a\":\"b\"}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,\"a\":\"b\",}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,,\"a\":\"b\"}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{\"a\":\"b\",,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{, ,}", jsonTestingMode) } - assertFailsWith { lenient.decodeFromString(Holder.serializer(), "{,\n,}", jsonTestingMode) } - } - - private fun prebuiltJson(): JsonObject { - return buildJsonObject { - put("literal", 1) - put("nullKey", JsonNull) - putJsonObject("nested") { - put("another literal", "some value") - } - put("\\. escaped", "\\. escaped") - put("\n new line", "\n new line") - } - } -} diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt deleted file mode 100644 index 1b79e27ef..000000000 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt +++ /dev/null @@ -1,28 +0,0 @@ -package kotlinx.serialization.json.internal - -internal actual class JsonStringBuilder actual constructor() { - private val sb = StringBuilder(128) - - actual fun append(value: Long) { - sb.append(value) - } - - actual fun append(ch: Char) { - sb.append(ch) - } - - actual fun append(string: String) { - sb.append(string) - } - - actual fun appendQuoted(string: String) { - sb.printQuoted(string) - } - - actual override fun toString(): String { - return sb.toString() - } - - actual fun release() { - } -} diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt new file mode 100644 index 000000000..806a1d843 --- /dev/null +++ b/formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt @@ -0,0 +1,29 @@ +package kotlinx.serialization.json.internal + +internal actual open class JsonToStringWriter actual constructor(): JsonWriter { + private val sb = StringBuilder(128) + + actual override fun writeLong(value: Long) { + sb.append(value) + } + + actual override fun writeChar(char: Char) { + sb.append(char) + } + + actual override fun write(text: String) { + sb.append(text) + } + + actual override fun writeQuoted(text: String) { + sb.printQuoted(text) + } + + actual override fun release() { + sb.clear() + } + + actual override fun toString(): String { + return sb.toString() + } +} diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt index be3a64db4..04d8149b8 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt @@ -20,16 +20,11 @@ public fun Json.encodeToStream( value: T, stream: OutputStream ) { - val result = JsonToWriterStringBuilder(stream) + val writer = JsonToJavaStreamWriter(stream) try { - val encoder = StreamingJsonEncoder( - result, this, - WriteMode.OBJ, - arrayOfNulls(WriteMode.values().size) - ) - encoder.encodeSerializableValue(serializer, value) + encodeByWriter(writer, serializer, value) } finally { - result.release() + writer.release() } } @@ -60,11 +55,7 @@ public fun Json.decodeFromStream( deserializer: DeserializationStrategy, stream: InputStream ): T { - val lexer = ReaderJsonLexer(stream) - val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor, null) - val result = input.decodeSerializableValue(deserializer) - lexer.expectEof() - return result + return decodeByReader(deserializer, JavaStreamSerialReader(stream)) } /** @@ -81,59 +72,6 @@ public fun Json.decodeFromStream( public inline fun Json.decodeFromStream(stream: InputStream): T = decodeFromStream(serializersModule.serializer(), stream) -/** - * Description of [decodeToSequence]'s JSON input shape. - * - * The sequence represents a stream of objects parsed one by one; - * [DecodeSequenceMode] defines a separator between these objects. - * Typically, these objects are not separated by meaningful characters ([WHITESPACE_SEPARATED]), - * or the whole stream is a large array of objects separated with commas ([ARRAY_WRAPPED]). - */ -@ExperimentalSerializationApi -public enum class DecodeSequenceMode { - /** - * Declares that objects in the input stream are separated by whitespace characters. - * - * The stream is read as multiple JSON objects separated by any number of whitespace characters between objects. Starting and trailing whitespace characters are also permitted. - * Each individual object is parsed lazily, when it is requested from the resulting sequence. - * - * Whitespace character is either ' ', '\n', '\r' or '\t'. - * - * Example of `WHITESPACE_SEPARATED` stream content: - * ``` - * """{"key": "value"}{"key": "value2"} {"key2": "value2"}""" - * ``` - */ - WHITESPACE_SEPARATED, - - /** - * Declares that objects in the input stream are wrapped in the JSON array. - * Each individual object in the array is parsed lazily when it is requested from the resulting sequence. - * - * The stream is read as multiple JSON objects wrapped into a JSON array. - * The stream must start with an array start character `[` and end with an array end character `]`, - * otherwise, [JsonDecodingException] is thrown. - * - * Example of `ARRAY_WRAPPED` stream content: - * ``` - * """[{"key": "value"}, {"key": "value2"},{"key2": "value2"}]""" - * ``` - */ - ARRAY_WRAPPED, - - /** - * Declares that parser itself should select between [WHITESPACE_SEPARATED] and [ARRAY_WRAPPED] modes. - * The selection is performed by looking on the first meaningful character of the stream. - * - * In most cases, auto-detection is sufficient to correctly parse an input. - * If the input is _whitespace-separated stream of the arrays_, parser could select an incorrect mode, - * for that [DecodeSequenceMode] must be specified explicitly. - * - * Example of an exceptional case: - * `[1, 2, 3] [4, 5, 6]\n[7, 8, 9]` - */ - AUTO_DETECT; -} /** * Transforms the given [stream] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. @@ -156,9 +94,7 @@ public fun Json.decodeToSequence( deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence { - val lexer = ReaderJsonLexer(stream) - val iter = JsonIterator(format, this, lexer, deserializer) - return Sequence { iter }.constrainOnce() + return decodeToSequenceByReader(JavaStreamSerialReader(stream), deserializer, format) } /** @@ -181,4 +117,3 @@ public inline fun Json.decodeToSequence( stream: InputStream, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence = decodeToSequence(stream, serializersModule.serializer(), format) - diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/ByteArrayPool.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/ByteArrayPool.kt new file mode 100644 index 000000000..a1ab1bc0b --- /dev/null +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/ByteArrayPool.kt @@ -0,0 +1,30 @@ +package kotlinx.serialization.json.internal + +internal object ByteArrayPool { + private val arrays = ArrayDeque() + private var charsTotal = 0 + /* + * Not really documented kill switch as a workaround for potential + * (unlikely) problems with memory consumptions. + */ + private val MAX_CHARS_IN_POOL = runCatching { + System.getProperty("kotlinx.serialization.json.pool.size").toIntOrNull() + }.getOrNull() ?: 2 * 1024 * 1024 // 2 MB seems to be a reasonable constraint, (1M of chars) + + fun take(): ByteArray { + /* + * Initially the pool is empty, so an instance will be allocated + * and the pool will be populated in the 'release' + */ + val candidate = synchronized(this) { + arrays.removeLastOrNull()?.also { charsTotal -= it.size } + } + return candidate ?: ByteArray(512) + } + + fun release(array: ByteArray) = synchronized(this) { + if (charsTotal + array.size >= MAX_CHARS_IN_POOL) return@synchronized + charsTotal += array.size + arrays.addLast(array) + } +} diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt similarity index 84% rename from formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt rename to formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt index 37766d993..e11c21c1d 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt @@ -25,41 +25,41 @@ package kotlinx.serialization.json.internal * 3) We pool char arrays in order to save excess resizes, allocations * and nulls-out of arrays. */ -internal actual open class JsonStringBuilder(@JvmField protected var array: CharArray) { - actual constructor(): this(CharArrayPool.take()) +internal actual class JsonToStringWriter : JsonWriter { + private var array: CharArray = CharArrayPool.take() + private var size = 0 - protected var size = 0 - - actual fun append(value: Long) { + actual override fun writeLong(value: Long) { // Can be hand-rolled, but requires a lot of code and corner-cases handling - append(value.toString()) + write(value.toString()) } - actual fun append(ch: Char) { + actual override fun writeChar(char: Char) { ensureAdditionalCapacity(1) - array[size++] = ch + array[size++] = char } - actual fun append(string: String) { - val length = string.length + actual override fun write(text: String) { + val length = text.length + if (length == 0) return ensureAdditionalCapacity(length) - string.toCharArray(array, size, 0, string.length) + text.toCharArray(array, size, 0, text.length) size += length } - actual fun appendQuoted(string: String) { - ensureAdditionalCapacity(string.length + 2) + actual override fun writeQuoted(text: String) { + ensureAdditionalCapacity(text.length + 2) val arr = array var sz = size arr[sz++] = '"' - val length = string.length - string.toCharArray(arr, sz, 0, length) + val length = text.length + text.toCharArray(arr, sz, 0, length) for (i in sz until sz + length) { val ch = arr[i].code // Do we have unescaped symbols? if (ch < ESCAPE_MARKERS.size && ESCAPE_MARKERS[ch] != 0.toByte()) { // Go to slow path - return appendStringSlowPath(i - sz, i, string) + return appendStringSlowPath(i - sz, i, text) } } // Update the state @@ -113,6 +113,10 @@ internal actual open class JsonStringBuilder(@JvmField protected var array: Char size = sz } + actual override fun release() { + CharArrayPool.release(array) + } + actual override fun toString(): String { return String(array, 0, size) } @@ -122,15 +126,11 @@ internal actual open class JsonStringBuilder(@JvmField protected var array: Char } // Old size is passed and returned separately to avoid excessive [size] field read - protected open fun ensureTotalCapacity(oldSize: Int, additional: Int): Int { + private fun ensureTotalCapacity(oldSize: Int, additional: Int): Int { val newSize = oldSize + additional if (array.size <= newSize) { array = array.copyOf(newSize.coerceAtLeast(oldSize * 2)) } return oldSize } - - actual open fun release() { - CharArrayPool.release(array) - } } diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToWriterStringBuilder.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToWriterStringBuilder.kt deleted file mode 100644 index c4069068b..000000000 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToWriterStringBuilder.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 java.io.OutputStream -import java.io.Writer -import java.nio.charset.Charset - - -internal class JsonToWriterStringBuilder(private val writer: Writer) : JsonStringBuilder( - // maybe this can also be taken from the pool, but currently initial char array size there is 128, which is too low. - CharArray(BATCH_SIZE) -) { - constructor(os: OutputStream, charset: Charset = Charsets.UTF_8): this(os.writer(charset).buffered(READER_BUF_SIZE)) - - override fun ensureTotalCapacity(oldSize: Int, additional: Int): Int { - val requiredSize = oldSize + additional - val currentSize = array.size - if (currentSize <= requiredSize) { - flush(oldSize) - if (additional > currentSize) { - // Handle strings that are longer than buffer: - // Ideally, we should make `ensureAdditionalCapacity` return boolean and fall back - // to per-symbol path in appendQuoted on large strings, - // but this approach is adequate for current stage, too. - array = CharArray(requiredSize.coerceAtLeast(currentSize * 2)) - } - return 0 - } - return oldSize - } - - private fun flush(sz: Int = size) { - writer.write(array, 0, sz) - size = 0 - } - - override fun release() { - flush() - writer.flush() - } -} - diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt new file mode 100644 index 000000000..17eac0a2a --- /dev/null +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt @@ -0,0 +1,259 @@ +package kotlinx.serialization.json.internal + +import java.io.InputStream +import java.io.OutputStream +import java.nio.charset.Charset + +internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWriter { + private val buffer = ByteArrayPool.take() + private var charArray = CharArrayPool.take() + private var indexInBuffer: Int = 0 + + override fun writeLong(value: Long) { + write(value.toString()) + } + + override fun writeChar(char: Char) { + writeUtf8CodePoint(char.code) + } + + override fun write(text: String) { + val length = text.length + ensureTotalCapacity(0, length) + text.toCharArray(charArray, 0, 0, length) + writeUtf8(charArray, length) + } + + override fun writeQuoted(text: String) { + ensureTotalCapacity(0, text.length + 2) + val arr = charArray + arr[0] = '"' + val length = text.length + text.toCharArray(arr, 1, 0, length) + for (i in 1 until 1 + length) { + val ch = arr[i].code + // Do we have unescaped symbols? + if (ch < ESCAPE_MARKERS.size && ESCAPE_MARKERS[ch] != 0.toByte()) { + // Go to slow path + return appendStringSlowPath(i, text) + } + } + // Update the state + // Capacity is not ensured because we didn't hit the slow path and thus guessed it properly in the beginning + + arr[length + 1] = '"' + + writeUtf8(arr, length + 2) + flush() + } + + private fun appendStringSlowPath(currentSize: Int, string: String) { + var sz = currentSize + for (i in currentSize - 1 until string.length) { + /* + * We ar already on slow path and haven't guessed the capacity properly. + * Reserve +2 for backslash-escaped symbols on each iteration + */ + sz = ensureTotalCapacity(sz, 2) + val ch = string[i].code + // Do we have unescaped symbols? + if (ch < ESCAPE_MARKERS.size) { + /* + * Escape markers are populated for backslash-escaped symbols. + * E.g. ESCAPE_MARKERS['\b'] == 'b'.toByte() + * Everything else is populated with either zeros (no escapes) + * or ones (unicode escape) + */ + when (val marker = ESCAPE_MARKERS[ch]) { + 0.toByte() -> { + charArray[sz++] = ch.toChar() + } + 1.toByte() -> { + val escapedString = ESCAPE_STRINGS[ch]!! + sz = ensureTotalCapacity(sz, escapedString.length) + escapedString.toCharArray(charArray, sz, 0, escapedString.length) + sz += escapedString.length + } + else -> { + charArray[sz] = '\\' + charArray[sz + 1] = marker.toInt().toChar() + sz += 2 + } + } + } else { + charArray[sz++] = ch.toChar() + } + } + ensureTotalCapacity(sz, 1) + charArray[sz++] = '"' + writeUtf8(charArray, sz) + flush() + } + + private fun ensureTotalCapacity(oldSize: Int, additional: Int): Int { + val newSize = oldSize + additional + if (charArray.size <= newSize) { + charArray = charArray.copyOf(newSize.coerceAtLeast(oldSize * 2)) + } + return oldSize + } + + override fun release() { + flush() + CharArrayPool.release(charArray) + ByteArrayPool.release(buffer) + } + + private fun flush() { + stream.write(buffer, 0, indexInBuffer) + indexInBuffer = 0 + } + + + @Suppress("NOTHING_TO_INLINE") + // ! you should never ask for more than the buffer size + private inline fun ensure(bytesCount: Int) { + if (rest() < bytesCount) { + flush() + } + } + + @Suppress("NOTHING_TO_INLINE") + // ! you should never ask for more than the buffer size + private inline fun write(byte: Int) { + buffer[indexInBuffer++] = byte.toByte() + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun rest(): Int { + return buffer.size - indexInBuffer + } + + /* + Sources taken from okio library with minor changes, see https://github.com/square/okio + */ + private fun writeUtf8(string: CharArray, count: Int) { + require(count >= 0) { "count < 0" } + require(count <= string.size) { "count > string.length: $count > ${string.size}" } + + // Transcode a UTF-16 Java String to UTF-8 bytes. + var i = 0 + while (i < count) { + var c = string[i].code + + when { + c < 0x80 -> { + // Emit a 7-bit character with 1 byte. + ensure(1) + write(c) // 0xxxxxxx + i++ + val runLimit = minOf(count, i + rest()) + + // Fast-path contiguous runs of ASCII characters. This is ugly, but yields a ~4x performance + // improvement over independent calls to writeByte(). + while (i < runLimit) { + c = string[i].code + if (c >= 0x80) break + write(c) // 0xxxxxxx + i++ + } + } + + c < 0x800 -> { + // Emit a 11-bit character with 2 bytes. + ensure(2) + write(c shr 6 or 0xc0) // 110xxxxx + write(c and 0x3f or 0x80) // 10xxxxxx + i++ + } + + c < 0xd800 || c > 0xdfff -> { + // Emit a 16-bit character with 3 bytes. + ensure(3) + write(c shr 12 or 0xe0) // 1110xxxx + write(c shr 6 and 0x3f or 0x80) // 10xxxxxx + write(c and 0x3f or 0x80) // 10xxxxxx + i++ + } + + else -> { + // c is a surrogate. Make sure it is a high surrogate & that its successor is a low + // surrogate. If not, the UTF-16 is invalid, in which case we emit a replacement + // character. + val low = (if (i + 1 < count) string[i + 1].code else 0) + if (c > 0xdbff || low !in 0xdc00..0xdfff) { + ensure(1) + write('?'.code) + i++ + } else { + // UTF-16 high surrogate: 110110xxxxxxxxxx (10 bits) + // UTF-16 low surrogate: 110111yyyyyyyyyy (10 bits) + // Unicode code point: 00010000000000000000 + xxxxxxxxxxyyyyyyyyyy (21 bits) + val codePoint = 0x010000 + (c and 0x03ff shl 10 or (low and 0x03ff)) + + // Emit a 21-bit character with 4 bytes. + ensure(4) + write(codePoint shr 18 or 0xf0) // 11110xxx + write(codePoint shr 12 and 0x3f or 0x80) // 10xxxxxx + write(codePoint shr 6 and 0x3f or 0x80) // 10xxyyyy + write(codePoint and 0x3f or 0x80) // 10yyyyyy + i += 2 + } + } + } + } + } + + /* + Sources taken from okio library with minor changes, see https://github.com/square/okio + */ + private fun writeUtf8CodePoint(codePoint: Int) { + when { + codePoint < 0x80 -> { + // Emit a 7-bit code point with 1 byte. + ensure(1) + write(codePoint) + } + codePoint < 0x800 -> { + // Emit a 11-bit code point with 2 bytes. + ensure(2) + write(codePoint shr 6 or 0xc0) // 110xxxxx + write(codePoint and 0x3f or 0x80) // 10xxxxxx + } + codePoint in 0xd800..0xdfff -> { + // Emit a replacement character for a partial surrogate. + ensure(1) + write('?'.code) + } + codePoint < 0x10000 -> { + // Emit a 16-bit code point with 3 bytes. + ensure(3) + write(codePoint shr 12 or 0xe0) // 1110xxxx + write(codePoint shr 6 and 0x3f or 0x80) // 10xxxxxx + write(codePoint and 0x3f or 0x80) // 10xxxxxx + } + codePoint <= 0x10ffff -> { + // Emit a 21-bit code point with 4 bytes. + ensure(4) + write(codePoint shr 18 or 0xf0) // 11110xxx + write(codePoint shr 12 and 0x3f or 0x80) // 10xxxxxx + write(codePoint shr 6 and 0x3f or 0x80) // 10xxyyyy + write(codePoint and 0x3f or 0x80) // 10yyyyyy + } + else -> { + throw JsonEncodingException("Unexpected code point: $codePoint") + } + } + } +} + +internal class JavaStreamSerialReader( + stream: InputStream, + charset: Charset = Charsets.UTF_8 +) : SerialReader { + private val reader = stream.reader(charset) + + override fun read(buffer: CharArray, bufferOffset: Int, count: Int): Int { + return reader.read(buffer, bufferOffset, count) + } +} diff --git a/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt b/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt deleted file mode 100644 index 1b79e27ef..000000000 --- a/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt +++ /dev/null @@ -1,28 +0,0 @@ -package kotlinx.serialization.json.internal - -internal actual class JsonStringBuilder actual constructor() { - private val sb = StringBuilder(128) - - actual fun append(value: Long) { - sb.append(value) - } - - actual fun append(ch: Char) { - sb.append(ch) - } - - actual fun append(string: String) { - sb.append(string) - } - - actual fun appendQuoted(string: String) { - sb.printQuoted(string) - } - - actual override fun toString(): String { - return sb.toString() - } - - actual fun release() { - } -} diff --git a/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt b/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt new file mode 100644 index 000000000..d996fc335 --- /dev/null +++ b/formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt @@ -0,0 +1,29 @@ +package kotlinx.serialization.json.internal + +internal actual open class JsonToStringWriter actual constructor(): JsonWriter { + private val sb = StringBuilder(128) + + actual override fun writeLong(value: Long) { + sb.append(value) + } + + actual override fun writeChar(char: Char) { + sb.append(char) + } + + actual override fun write(text: String) { + sb.append(text) + } + + actual override fun writeQuoted(text: String) { + sb.printQuoted(text) + } + + actual override fun release() { + // nothing to flush + } + + actual override fun toString(): String { + return sb.toString() + } +} diff --git a/gradle.properties b/gradle.properties index 0c58f546c..3a5aa20a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,7 @@ validator_version=0.7.1 knit_version=0.3.0 coroutines_version=1.3.9 kover_version=0.4.2 +okio_version=3.1.0 kover.enabled=true diff --git a/gradle/kover.gradle b/gradle/kover.gradle index 214520d0b..9eacea4e8 100644 --- a/gradle/kover.gradle +++ b/gradle/kover.gradle @@ -12,7 +12,7 @@ tasks.withType(Test) { task -> } tasks.koverVerify { // Core is mainly uncovered because a lot of serializers are tested with JSON - def minPercentage = (project.name.contains("core") || project.name.contains("properties")) ? 45 : 80 + def minPercentage = (project.name.contains("core") || project.name.contains("properties")|| project.name.contains("json-okio")) ? 45 : 80 rule { name = "Minimal line coverage rate in percents" bound { diff --git a/gradle/native-targets.gradle b/gradle/native-targets.gradle index 909fcec1b..df480a059 100644 --- a/gradle/native-targets.gradle +++ b/gradle/native-targets.gradle @@ -67,6 +67,10 @@ def getHostName() { return 'unknown' } +static def doesNotDependOnOkio(project) { + return !project.name.contains("json-okio") && !project.name.contains("json-tests") +} + kotlin { targets { def manager = project.ext.hostManager @@ -93,14 +97,18 @@ kotlin { } else { // Linux addTarget(presets.linuxX64) - addTarget(presets.linuxArm32Hfp) - addTarget(presets.linuxArm64) + if (doesNotDependOnOkio(project)) { + addTarget(presets.linuxArm32Hfp) + addTarget(presets.linuxArm64) + } // Mac & iOS addTarget(presets.macosX64) addTarget(presets.iosArm64) - addTarget(presets.iosArm32) + if (doesNotDependOnOkio(project)) { + addTarget(presets.iosArm32) + } addTarget(presets.iosX64) addTarget(presets.watchosX86) @@ -119,7 +127,9 @@ kotlin { // Windows addTarget(presets.mingwX64) - addTarget(presets.mingwX86) + if (doesNotDependOnOkio(project)) { + addTarget(presets.mingwX86) + } } if (project.ext.nativeState == NativeState.HOST) { diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index c16999ada..912050cef 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -9,8 +9,9 @@ apply plugin: 'signing' apply from: project.rootProject.file('gradle/maven-metadata.gradle') -def isMultiplatform = project.name in ["kotlinx-serialization-core", "kotlinx-serialization-json","kotlinx-serialization-protobuf", - "kotlinx-serialization-cbor", "kotlinx-serialization-properties"] +def isMultiplatform = project.name in ["kotlinx-serialization-core", "kotlinx-serialization-json", "kotlinx-serialization-json-okio", + "kotlinx-serialization-json-tests", "kotlinx-serialization-protobuf", "kotlinx-serialization-cbor", + "kotlinx-serialization-properties"] def isBom = project.name == "kotlinx-serialization-bom" if (!isBom) { diff --git a/settings.gradle b/settings.gradle index 10251efc5..01d4ea62f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,12 @@ project(':kotlinx-serialization-bom').projectDir = file('./bom') include ':kotlinx-serialization-json' project(':kotlinx-serialization-json').projectDir = file('./formats/json') +include ':kotlinx-serialization-json-okio' +project(':kotlinx-serialization-json-okio').projectDir = file('./formats/json-okio') + +include ':kotlinx-serialization-json-tests' +project(':kotlinx-serialization-json-tests').projectDir = file('./formats/json-tests') + include ':kotlinx-serialization-protobuf' project(':kotlinx-serialization-protobuf').projectDir = file('./formats/protobuf')