From 922c709046768fead040ec4d116bb1f6ee3df694 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 13 Apr 2022 23:33:36 +0300 Subject: [PATCH 01/27] IO Streams prototype --- docs/formats.md | 76 +---- docs/serialization-guide.md | 4 +- .../api/kotlinx-serialization-json-okio.api | 7 + formats/json-okio/build.gradle.kts | 31 ++ .../kotlinx/serialization/json/OkioStreams.kt | 120 ++++++++ .../json/internal/OkioJsonStreams.kt | 50 +++ .../kotlinx/serialization/json/TestTest.kt | 54 ++++ .../json/api/kotlinx-serialization-json.api | 24 ++ .../src/kotlinx/serialization/json/Json.kt | 63 +++- .../serialization/json/internal/Composers.kt | 30 +- .../json/internal/JsonIterator.kt | 0 .../json/internal/JsonStreams.kt | 65 ++++ .../json/internal/JsonStringBuilder.kt | 10 - .../json/internal/JsonToStringWriter.kt | 10 + .../json/internal/StreamingJsonEncoder.kt | 8 +- .../serialization/json/internal/StringOps.kt | 4 +- .../json/internal/lexer}/JsonLexerJvm.kt | 13 +- .../json/internal/JsonStringBuilder.kt | 28 -- .../json/internal/JsonToStringWriter.kt | 29 ++ .../kotlinx/serialization/json/JvmStreams.kt | 75 +---- .../json/internal/ByteArrayPool.kt | 30 ++ ...StringBuilder.kt => JsonToStringWriter.kt} | 42 +-- .../internal/JsonToWriterStringBuilder.kt | 45 --- .../json/internal/JvmJsonStreams.kt | 288 ++++++++++++++++++ .../features/JsonJvmStreamsTest.kt | 5 - .../json/internal/JsonStringBuilder.kt | 28 -- .../json/internal/JsonToStringWriter.kt | 29 ++ settings.gradle | 3 + 28 files changed, 856 insertions(+), 315 deletions(-) create mode 100644 formats/json-okio/api/kotlinx-serialization-json-okio.api create mode 100644 formats/json-okio/build.gradle.kts create mode 100644 formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt create mode 100644 formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt create mode 100644 formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt rename formats/json/{jvmMain => commonMain}/src/kotlinx/serialization/json/internal/JsonIterator.kt (100%) create mode 100644 formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt delete mode 100644 formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt create mode 100644 formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt rename formats/json/{jvmMain/src/kotlinx/serialization/json/internal => commonMain/src/kotlinx/serialization/json/internal/lexer}/JsonLexerJvm.kt (93%) delete mode 100644 formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt create mode 100644 formats/json/jsMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt create mode 100644 formats/json/jvmMain/src/kotlinx/serialization/json/internal/ByteArrayPool.kt rename formats/json/jvmMain/src/kotlinx/serialization/json/internal/{JsonStringBuilder.kt => JsonToStringWriter.kt} (84%) delete mode 100644 formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonToWriterStringBuilder.kt create mode 100644 formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt delete mode 100644 formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonStringBuilder.kt create mode 100644 formats/json/nativeMain/src/kotlinx/serialization/json/internal/JsonToStringWriter.kt diff --git a/docs/formats.md b/docs/formats.md index 288981e3f..92f30299a 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -435,62 +435,6 @@ Per the standard packed fields can only be used on primitive numeric types. The Per the [format description](https://developers.google.com/protocol-buffers/docs/encoding#packed) the parser ignores the annotation, but rather reads list in either packed or repeated format. -### ProtoBuf schema generator (experimental) - -As mentioned above, when working with protocol buffers you usually use a ".proto" file and a code generator for your -language. This includes the code to serialize your message to an output stream and deserialize it from an input stream. -When using Kotlin Serialization this step is not necessary because your `@Serializable` Kotlin data types are used as the -source for the schema. - -This is very convenient for Kotlin-to-Kotlin communication, but makes interoperability between languages complicated. -Fortunately, you can use the ProtoBuf schema generator to output the ".proto" representation of your messages. You can -keep your Kotlin classes as a source of truth and use traditional protoc compilers for other languages at the same time. - -As an example, we can display the following data class's ".proto" schema as follows. - - - -```kotlin -@Serializable -data class SampleData( - val amount: Long, - val description: String?, - val department: String = "QA" -) -fun main() { - val descriptors = listOf(SampleData.serializer().descriptor) - val schemas = ProtoBufSchemaGenerator.generateSchemaText(descriptors) - println(schemas) -} -``` -> You can get the full code [here](../guide/example/example-formats-08.kt). - -Which would output as follows. - -```text -syntax = "proto2"; - - -// serial name 'example.exampleFormats08.SampleData' -message SampleData { - required int64 amount = 1; - optional string description = 2; - // WARNING: a default value decoded when value is missing - optional string department = 3; -} - -``` - - - -Note that since default values are not represented in ".proto" files, a warning is generated when one appears in the schema. - -See the documentation for [ProtoBufSchemaGenerator] for more information. - ## Properties (experimental) Kotlin Serialization can serialize a class into a flat map with `String` keys via @@ -519,7 +463,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-09.kt). +> You can get the full code [here](../guide/example/example-formats-08.kt). The resulting map has dot-separated keys representing keys of the nested objects. @@ -599,7 +543,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-10.kt). +> You can get the full code [here](../guide/example/example-formats-09.kt). As a result, we got all the primitive values in our object graph visited and put into a list in _serial_ order. @@ -701,7 +645,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-11.kt). +> You can get the full code [here](../guide/example/example-formats-10.kt). Now we can convert a list of primitives back to an object tree. @@ -792,7 +736,7 @@ fun main() { } --> -> You can get the full code [here](../guide/example/example-formats-12.kt). +> You can get the full code [here](../guide/example/example-formats-11.kt). - -[ProtoBufSchemaGenerator]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-protobuf/kotlinx.serialization.protobuf.schema/-proto-buf-schema-generator/index.html - diff --git a/docs/serialization-guide.md b/docs/serialization-guide.md index e3f28eae7..3506fcf06 100644 --- a/docs/serialization-guide.md +++ b/docs/serialization-guide.md @@ -115,7 +115,7 @@ Once the project is set up, we can start serializing some classes. * [Explicit nulls](json.md#explicit-nulls) * [Allowing structured map keys](json.md#allowing-structured-map-keys) * [Allowing special floating-point values](json.md#allowing-special-floating-point-values) - * [Class discriminator for polymorphism](json.md#class-discriminator-for-polymorphism) + * [Class discriminator](json.md#class-discriminator) * [Json elements](json.md#json-elements) * [Parsing to Json element](json.md#parsing-to-json-element) * [Types of Json elements](json.md#types-of-json-elements) @@ -140,8 +140,6 @@ Once the project is set up, we can start serializing some classes. * [Field numbers](formats.md#field-numbers) * [Integer types](formats.md#integer-types) * [Lists as repeated fields](formats.md#lists-as-repeated-fields) - * [Packed fields](formats.md#packed-fields) - * [ProtoBuf schema generator (experimental)](formats.md#protobuf-schema-generator-experimental) * [Properties (experimental)](formats.md#properties-experimental) * [Custom formats (experimental)](formats.md#custom-formats-experimental) * [Basic encoder](formats.md#basic-encoder) 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..9aa2ea3ba --- /dev/null +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -0,0 +1,7 @@ +public final class kotlinx/serialization/json/OkioStreamsKt { + public static final fun decodeFromOkio (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; + public static final fun decodeOkioToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeOkioToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; + public static final fun encodeToOkio (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/BufferedSink;)V +} + diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts new file mode 100644 index 000000000..916007aee --- /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")) + compileOnly("com.squareup.okio:okio-multiplatform:3.0.0-alpha.9") + } + } + val commonTest by getting { + dependencies { + implementation("com.squareup.okio:okio-multiplatform:3.0.0-alpha.9") + } + } + } +} + +project.configureJava9ModuleInfo() diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt new file mode 100644 index 000000000..d4586e0da --- /dev/null +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt @@ -0,0 +1,120 @@ +package kotlinx.serialization.json + +import kotlinx.serialization.* +import kotlinx.serialization.json.internal.* +import kotlinx.serialization.json.internal.JsonToOkioStreamWriter +import kotlinx.serialization.json.internal.decodeToSequence +import okio.BufferedSink +import okio.BufferedSource + +/** +* Serializes the [value] with [serializer] into a [stream] using JSON format and UTF-8 encoding. +* +* @throws [SerializationException] if the given value cannot be serialized to JSON. +* @throws [IOException] If an I/O error occurs and stream can't be written to. +*/ +@ExperimentalSerializationApi +public fun Json.encodeToOkio( + serializer: SerializationStrategy, + value: T, + target: BufferedSink +) { + val writer = JsonToOkioStreamWriter(target) + try { + encodeByWriter(writer, serializer, value) + } finally { + writer.release() + } +} + +/** + * Serializes given [value] to [stream] using UTF-8 encoding and serializer retrieved from the reified type parameter. + * + * @throws [SerializationException] if the given value cannot be serialized to JSON. + * @throws [IOException] If an I/O error occurs and stream can't be written to. + */ +@ExperimentalSerializationApi +public inline fun Json.encodeToOkio( + value: T, + target: BufferedSink +): Unit = + encodeToOkio(serializersModule.serializer(), value, target) + + + +/** + * Deserializes JSON from [source] using UTF-8 encoding to a value of type [T] using [deserializer]. + * + * 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 [IOException] If an I/O error occurs and stream can't be read from. + */ +@ExperimentalSerializationApi +public fun Json.decodeFromOkio( + deserializer: DeserializationStrategy, + source: BufferedSource +): T { + return decodeByReader(deserializer, OkioSerialReader(source)) +} + +/** + * Deserializes the contents of given [source] to the value of type [T] using UTF-8 encoding and + * deserializer retrieved from the reified type parameter. + * + * 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 [IOException] If an I/O error occurs and stream can't be read from. + */ +@ExperimentalSerializationApi +public inline fun Json.decodeFromOkio(source: BufferedSource): T = + decodeFromOkio(serializersModule.serializer(), source) + + +/** + * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. + * Unlike [decodeFromStream], [source] is allowed to have more than one element, separated as [format] declares. + * + * 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 [IOException] from decoder. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [IOException] If an I/O error occurs and stream can't be read from. + */ +@ExperimentalSerializationApi +public fun Json.decodeOkioToSequence( + source: BufferedSource, + deserializer: DeserializationStrategy, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence { + return decodeToSequence(OkioSerialReader(source), 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 [decodeFromStream], [source] is allowed to have more than one element, separated as [format] declares. + * + * 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 [IOException] from decoder. + * + * @throws [SerializationException] if the given JSON input cannot be deserialized to the value of type [T]. + * @throws [IOException] If an I/O error occurs and stream can't be read from. + */ +@ExperimentalSerializationApi +public inline fun Json.decodeOkioToSequence( + source: BufferedSource, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence = decodeOkioToSequence(source, serializersModule.serializer(), format) diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt new file mode 100644 index 000000000..dabe2753c --- /dev/null +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt @@ -0,0 +1,50 @@ +package kotlinx.serialization.json.internal + +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/commonTest/src/kotlinx/serialization/json/TestTest.kt b/formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt new file mode 100644 index 000000000..2095879eb --- /dev/null +++ b/formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt @@ -0,0 +1,54 @@ +package kotlinx.serialization.json + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import okio.* +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + + +class TestTest { + private val strLen = 1024 * 2 + 42 + + @Serializable + data class StringHolder(val data: String) + + @Test + fun testParsesStringsLongerThanBuffer() { + val str = "a".repeat(strLen) + val input = """{"data":"$str"}""" + assertEquals(input, Json.encodeViaOkio(StringHolder.serializer(), StringHolder(str))) + } + @Test + fun test2() { + val str = "a".repeat(strLen) + + val buffer = Buffer() + + Json.encodeToOkio(StringHolder.serializer(), StringHolder(str), buffer) + + val result = Json.decodeFromOkio(StringHolder.serializer(), buffer) + + assertEquals(StringHolder(str), result) + } + @Test + fun test4() { + val str = "a".repeat(strLen) + + val buffer = Buffer() + + Json.encodeToOkio(StringHolder(str), buffer) + Json.decodeOkioToSequence(buffer, StringHolder.serializer()) + } +} + +fun Json.encodeViaOkio(serializer: KSerializer, value: T): String { + val limited = Buffer() + + encodeToOkio(serializer, value, limited) + + return limited.readUtf8() + +} diff --git a/formats/json/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index cb5aaeb3e..e7dbc27d6 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -358,3 +358,27 @@ 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 decodeToSequence (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/SerialReader;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeToSequence$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/StringOpsKt { + public static final fun getESCAPE_MARKERS ()[B + public static final fun getESCAPE_STRINGS ()[Ljava/lang/String; +} + diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt b/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt index 8f1f02fd6..c9eabab3a 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 [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; +} + /** * 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..4fab95a80 --- /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) + val result = input.decodeSerializableValue(deserializer) + lexer.expectEof() + return result +} + +@InternalSerializationApi +@ExperimentalSerializationApi +public fun Json.decodeToSequence( + 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.decodeToSequence( + reader: SerialReader, + format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT +): Sequence = decodeToSequence(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/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..45c520df1 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt @@ -13,7 +13,7 @@ private fun toHexChar(i: Int) : Char { } @SharedImmutable -internal val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { +public val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { for (c in 0..0x1f) { val c1 = toHexChar(c shr 12) val c2 = toHexChar(c shr 8) @@ -31,7 +31,7 @@ internal val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { } @SharedImmutable -internal val ESCAPE_MARKERS: ByteArray = ByteArray(93).apply { +public val ESCAPE_MARKERS: ByteArray = ByteArray(93).apply { for (c in 0..0x1f) { this[c] = 1.toByte() } diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt similarity index 93% rename from formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt rename to formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt index 28ec2cfc3..5e2683022 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JsonLexerJvm.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt @@ -4,9 +4,6 @@ package kotlinx.serialization.json.internal -import java.io.* -import java.nio.charset.Charset - internal const val BATCH_SIZE = 16 * 1024 private const val DEFAULT_THRESHOLD = 128 @@ -26,18 +23,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 +70,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,7 +163,7 @@ 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) { 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..938b4e677 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 decodeToSequence(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..b10c86ee8 --- /dev/null +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt @@ -0,0 +1,288 @@ +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 array = CharArrayPool.take() + private var index: 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(array, 0, 0, length) + writeUtf8(array, 0, length) + } + + override fun writeQuoted(text: String) { + ensureTotalCapacity(0, text.length + 2) + val arr = array + 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, 0, 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() -> { + array[sz++] = ch.toChar() + } + 1.toByte() -> { + val escapedString = ESCAPE_STRINGS[ch]!! + sz = ensureTotalCapacity(sz, escapedString.length) + escapedString.toCharArray(array, sz, 0, escapedString.length) + sz += escapedString.length + } + else -> { + array[sz] = '\\' + array[sz + 1] = marker.toInt().toChar() + sz += 2 + } + } + } else { + array[sz++] = ch.toChar() + } + } + ensureTotalCapacity(sz, 1) + array[sz++] = '"' + writeUtf8(array, 0, sz) + flush() + } + + 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 + } + +// override fun writeQuoted(text: String) { +// val escapeStrings = ESCAPE_STRINGS +// val length = text.length +// +// writeUtf8CodePoint(DOUBLE_QUOTES_CODE) +// var lastPos = 0 +// for (i in 0 until length) { +// val c = text[i].code +// if (c < escapeStrings.size) { +// escapeStrings[c]?.let { +// writeUtf8(text, lastPos, i) // flush prev +// writeUtf8(it) +// lastPos = i + 1 +// } +// } +// } +// +// if (lastPos != 0) writeUtf8(text, lastPos, length) +// else writeUtf8(text) +// writeUtf8CodePoint(DOUBLE_QUOTES_CODE) +// } + + override fun release() { + flush() + CharArrayPool.release(array) + ByteArrayPool.release(buffer) + } + + private fun flush() { + stream.write(buffer, 0, index) + index = 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[index++] = byte.toByte() + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun rest(): Int { + return buffer.size - index + } + + private fun writeUtf8(string: CharArray, beginIndex: Int, endIndex: Int) { + require(beginIndex >= 0) { "beginIndex < 0: $beginIndex" } + require(endIndex >= beginIndex) { "endIndex < beginIndex: $endIndex < $beginIndex" } + require(endIndex <= string.size) { "endIndex > string.length: $endIndex > ${string.size}" } + + // Transcode a UTF-16 Java String to UTF-8 bytes. + var i = beginIndex + while (i < endIndex) { + 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(endIndex, 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) + /* ktlint-disable no-multi-spaces */ + write(c shr 6 or 0xc0) // 110xxxxx + write(c and 0x3f or 0x80) // 10xxxxxx + /* ktlint-enable no-multi-spaces */ + i++ + } + + c < 0xd800 || c > 0xdfff -> { + // Emit a 16-bit character with 3 bytes. + ensure(3) + /* ktlint-disable no-multi-spaces */ + write(c shr 12 or 0xe0) // 1110xxxx + write(c shr 6 and 0x3f or 0x80) // 10xxxxxx + write(c and 0x3f or 0x80) // 10xxxxxx + /* ktlint-enable no-multi-spaces */ + 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 < endIndex) 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) + /* ktlint-disable no-multi-spaces */ + 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 + /* ktlint-enable no-multi-spaces */ + i += 2 + } + } + } + } + } + + 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) + /* ktlint-disable no-multi-spaces */ + write(codePoint shr 6 or 0xc0) // 110xxxxx + write(codePoint and 0x3f or 0x80) // 10xxxxxx + /* ktlint-enable no-multi-spaces */ + } + 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) + /* ktlint-disable no-multi-spaces */ + write(codePoint shr 12 or 0xe0) // 1110xxxx + write(codePoint shr 6 and 0x3f or 0x80) // 10xxxxxx + write(codePoint and 0x3f or 0x80) // 10xxxxxx + /* ktlint-enable no-multi-spaces */ + } + codePoint <= 0x10ffff -> { + // Emit a 21-bit code point with 4 bytes. + ensure(4) + /* ktlint-disable no-multi-spaces */ + 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 + /* ktlint-enable no-multi-spaces */ + } + else -> { + throw IllegalArgumentException("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/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt b/formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt index 0de89d9c5..d2e86b2d3 100644 --- a/formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt +++ b/formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt @@ -72,16 +72,11 @@ class JsonJvmStreamsTest { fun testRandomEscapeSequences() { repeat(1000) { val s = generateRandomUnicodeString(strLen) - try { val serializer = String.serializer() val b = ByteArrayOutputStream() Json.encodeToStream(serializer, s, b) val restored = Json.decodeFromStream(serializer, ByteArrayInputStream(b.toByteArray())) assertEquals(s, restored) - } catch (e: Throwable) { - // Not assertion error to preserve cause - throw IllegalStateException("Unexpectedly failed test, cause string: $s", e) - } } } 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/settings.gradle b/settings.gradle index 10251efc5..f6472f1a1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,9 @@ 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-protobuf' project(':kotlinx-serialization-protobuf').projectDir = file('./formats/protobuf') From 62c6c0ae9ca79bc66ce8d3dd1b8742d6dce300ba Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 11:20:03 +0300 Subject: [PATCH 02/27] review fixes --- .../api/kotlinx-serialization-json-okio.api | 2 +- .../json/{ => okio}/OkioStreams.kt | 31 ++++++++++--------- .../{ => okio}/internal/OkioJsonStreams.kt | 9 +++++- .../serialization/json/{ => okio}/TestTest.kt | 9 ++++-- 4 files changed, 31 insertions(+), 20 deletions(-) rename formats/json-okio/commonMain/src/kotlinx/serialization/json/{ => okio}/OkioStreams.kt (80%) rename formats/json-okio/commonMain/src/kotlinx/serialization/json/{ => okio}/internal/OkioJsonStreams.kt (80%) rename formats/json-okio/commonTest/src/kotlinx/serialization/json/{ => okio}/TestTest.kt (86%) diff --git a/formats/json-okio/api/kotlinx-serialization-json-okio.api b/formats/json-okio/api/kotlinx-serialization-json-okio.api index 9aa2ea3ba..234bea703 100644 --- a/formats/json-okio/api/kotlinx-serialization-json-okio.api +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -1,4 +1,4 @@ -public final class kotlinx/serialization/json/OkioStreamsKt { +public final class kotlinx/serialization/json/okio/OkioStreamsKt { public static final fun decodeFromOkio (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; public static final fun decodeOkioToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; public static synthetic fun decodeOkioToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt similarity index 80% rename from formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt rename to formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt index d4586e0da..ddf21da85 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -1,17 +1,23 @@ -package kotlinx.serialization.json +/* + * 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.internal.JsonToOkioStreamWriter +import kotlinx.serialization.json.okio.internal.JsonToOkioStreamWriter import kotlinx.serialization.json.internal.decodeToSequence +import kotlinx.serialization.json.okio.internal.OkioSerialReader import okio.BufferedSink import okio.BufferedSource /** -* Serializes the [value] with [serializer] into a [stream] using JSON format and UTF-8 encoding. +* Serializes the [value] with [serializer] into a [target] using JSON format and UTF-8 encoding. * * @throws [SerializationException] if the given value cannot be serialized to JSON. -* @throws [IOException] If an I/O error occurs and stream can't be written to. */ @ExperimentalSerializationApi public fun Json.encodeToOkio( @@ -28,10 +34,9 @@ public fun Json.encodeToOkio( } /** - * Serializes given [value] to [stream] using UTF-8 encoding and serializer retrieved from the reified type parameter. + * Serializes given [value] to [target] using UTF-8 encoding and serializer retrieved from the reified type parameter. * * @throws [SerializationException] if the given value cannot be serialized to JSON. - * @throws [IOException] If an I/O error occurs and stream can't be written to. */ @ExperimentalSerializationApi public inline fun Json.encodeToOkio( @@ -45,11 +50,10 @@ public inline fun Json.encodeToOkio( /** * Deserializes JSON from [source] using UTF-8 encoding to a value of type [T] using [deserializer]. * - * Note that this functions expects that exactly one object would be present in the stream + * 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 [IOException] If an I/O error occurs and stream can't be read from. */ @ExperimentalSerializationApi public fun Json.decodeFromOkio( @@ -67,7 +71,6 @@ public fun Json.decodeFromOkio( * 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 [IOException] If an I/O error occurs and stream can't be read from. */ @ExperimentalSerializationApi public inline fun Json.decodeFromOkio(source: BufferedSource): T = @@ -76,7 +79,7 @@ public inline fun Json.decodeFromOkio(source: BufferedSource): T = /** * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. - * Unlike [decodeFromStream], [source] is allowed to have more than one element, separated as [format] declares. + * Unlike [decodeFromOkio], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. @@ -84,10 +87,9 @@ public inline fun Json.decodeFromOkio(source: BufferedSource): T = * * **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 [IOException] from decoder. + * 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 [IOException] If an I/O error occurs and stream can't be read from. */ @ExperimentalSerializationApi public fun Json.decodeOkioToSequence( @@ -100,7 +102,7 @@ public fun Json.decodeOkioToSequence( /** * 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 [decodeFromStream], [source] is allowed to have more than one element, separated as [format] declares. + * Unlike [decodeFromOkio], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. @@ -108,10 +110,9 @@ public fun Json.decodeOkioToSequence( * * **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 [IOException] from decoder. + * 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 [IOException] If an I/O error occurs and stream can't be read from. */ @ExperimentalSerializationApi public inline fun Json.decodeOkioToSequence( diff --git a/formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt similarity index 80% rename from formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt rename to formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt index dabe2753c..b72b133d0 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/internal/OkioJsonStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/internal/OkioJsonStreams.kt @@ -1,5 +1,12 @@ -package kotlinx.serialization.json.internal +/* + * 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.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 { diff --git a/formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt b/formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt similarity index 86% rename from formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt rename to formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt index 2095879eb..dbcd46990 100644 --- a/formats/json-okio/commonTest/src/kotlinx/serialization/json/TestTest.kt +++ b/formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt @@ -1,12 +1,15 @@ -package kotlinx.serialization.json +/* + * 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.KSerializer import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json import okio.* import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue class TestTest { From 403024160a0c44e349c1e9331bbfd6ff62e82e15 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 12:08:18 +0300 Subject: [PATCH 03/27] disable MinGW x86 target --- formats/json-okio/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 916007aee..e61fc0525 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -12,6 +12,8 @@ apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) kotlin { + targets.removeIf { it.name == "mingwX86" } + sourceSets { val commonMain by getting { dependencies { From ec82d13d147a0cd0c6e1462c75db77b9b3e5c527 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 12:16:43 +0300 Subject: [PATCH 04/27] disable Linux Arm x64 target --- formats/json-okio/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index e61fc0525..6a3549a3d 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -12,7 +12,7 @@ apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) kotlin { - targets.removeIf { it.name == "mingwX86" } + targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" } sourceSets { val commonMain by getting { From a39b01446c74b4433bc00750a37bd65b250deae4 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 12:26:17 +0300 Subject: [PATCH 05/27] disable Linux Arm 32 HFP target --- formats/json-okio/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 6a3549a3d..b051e774a 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -12,7 +12,7 @@ apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) kotlin { - targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" } + targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" || it.name == "linuxArm32Hfp" } sourceSets { val commonMain by getting { From 58d780e498430f6e469fe255c368dc23eb0cd836 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 12:29:48 +0300 Subject: [PATCH 06/27] disable iOS arm 32 target --- formats/json-okio/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index b051e774a..2b482387f 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -12,7 +12,7 @@ apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) kotlin { - targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" || it.name == "linuxArm32Hfp" } + targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" || it.name == "linuxArm32Hfp" || it.name == "iosArm32" } sourceSets { val commonMain by getting { From f6fece34b9372095175c9154a85c49b9eb787f06 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 12:39:20 +0300 Subject: [PATCH 07/27] Change dependency --- formats/json-okio/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 2b482387f..4dde6b104 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -19,12 +19,12 @@ kotlin { dependencies { api(project(":kotlinx-serialization-core")) api(project(":kotlinx-serialization-json")) - compileOnly("com.squareup.okio:okio-multiplatform:3.0.0-alpha.9") + compileOnly("com.squareup.okio:okio:3.1.0") } } val commonTest by getting { dependencies { - implementation("com.squareup.okio:okio-multiplatform:3.0.0-alpha.9") + implementation("com.squareup.okio:okio:3.1.0") } } } From 4cd82f2441db5d9aaa39195ae9706341a57094c7 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 27 Apr 2022 13:54:51 +0300 Subject: [PATCH 08/27] fixes --- formats/json-okio/build.gradle.kts | 4 +--- gradle/kover.gradle | 2 +- gradle/native-targets.gradle | 14 ++++++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 4dde6b104..9cdc4afe6 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -12,14 +12,12 @@ apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) kotlin { - targets.removeIf { it.name == "mingwX86" || it.name == "linuxArm64" || it.name == "linuxArm32Hfp" || it.name == "iosArm32" } - sourceSets { val commonMain by getting { dependencies { api(project(":kotlinx-serialization-core")) api(project(":kotlinx-serialization-json")) - compileOnly("com.squareup.okio:okio:3.1.0") + implementation("com.squareup.okio:okio:3.1.0") } } val commonTest by getting { 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..17bcaac32 100644 --- a/gradle/native-targets.gradle +++ b/gradle/native-targets.gradle @@ -93,14 +93,18 @@ kotlin { } else { // Linux addTarget(presets.linuxX64) - addTarget(presets.linuxArm32Hfp) - addTarget(presets.linuxArm64) + if (!project.name.contains("json-okio")) { + addTarget(presets.linuxArm32Hfp) + addTarget(presets.linuxArm64) + } // Mac & iOS addTarget(presets.macosX64) addTarget(presets.iosArm64) - addTarget(presets.iosArm32) + if (!project.name.contains("json-okio")) { + addTarget(presets.iosArm32) + } addTarget(presets.iosX64) addTarget(presets.watchosX86) @@ -119,7 +123,9 @@ kotlin { // Windows addTarget(presets.mingwX64) - addTarget(presets.mingwX86) + if (!project.name.contains("json-okio")) { + addTarget(presets.mingwX86) + } } if (project.ext.nativeState == NativeState.HOST) { From c336eec98c0c55b80eb16128059899ce518b579c Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Thu, 28 Apr 2022 05:33:58 +0300 Subject: [PATCH 09/27] fixes --- formats/json-okio/gradle.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 formats/json-okio/gradle.properties 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 From 17dd81388e1621292275424e682ccc0fa035a9eb Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Thu, 28 Apr 2022 06:30:20 +0300 Subject: [PATCH 10/27] mark publication as a multiplatform --- gradle/publishing.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index c16999ada..740b5c632 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -9,8 +9,8 @@ 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-protobuf", "kotlinx-serialization-cbor", "kotlinx-serialization-properties"] def isBom = project.name == "kotlinx-serialization-bom" if (!isBom) { From 50bd0b6d51a02a5dd1a860aea9557a6d4c443633 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 18 May 2022 22:03:37 +0300 Subject: [PATCH 11/27] tests --- docs/formats.md | 1 - docs/serialization-guide.md | 3 +- formats/json-tests/build.gradle.kts | 50 +++++++ .../ClassWithMultipleMasksTest.kt | 0 .../serialization/EncodingCollectionsTest.kt | 0 .../serialization/EncodingExtensionsTest.kt | 0 .../serialization/EnumSerializationTest.kt | 0 .../GenericSerializersOnFileTest.kt | 0 .../serialization/JsonOverwriteKeyTest.kt | 0 .../src/kotlinx/serialization/JsonPathTest.kt | 0 ...tNullSerializersCompatibilityOnFileTest.kt | 6 +- .../serialization/PolymorphismTestData.kt | 0 .../serialization/SerializableClasses.kt | 0 .../SerializationForNullableTypeOnFileTest.kt | 0 .../SerializerForNullableTypeTest.kt | 0 .../serialization/SerializersLookupTest.kt | 0 .../src/kotlinx/serialization/TuplesTest.kt | 0 .../kotlinx/serialization/UmbrellaTypes.kt | 0 .../serialization/UnknownElementIndexTest.kt | 0 .../builtins/KeyValueSerializersTest.kt | 0 .../features/BinaryPayloadExampleTest.kt | 0 .../features/ByteArraySerializerTest.kt | 0 .../features/CollectionSerializerTest.kt | 2 - .../features/ContextAndPolymorphicTest.kt | 3 +- .../DerivedContextualSerializerTest.kt | 0 .../features/GenericCustomSerializerTest.kt | 2 +- .../serialization/features/InheritanceTest.kt | 0 .../features/JsonClassDiscriminatorTest.kt | 0 .../serialization/features/JsonNamesTest.kt | 0 .../features/LocalClassesTest.kt | 0 .../features/LongAsStringTest.kt | 0 .../features/ObjectSerialization.kt | 0 .../features/PartiallyCustomSerializerTest.kt | 0 .../features/PolymorphicOnClassesTest.kt | 0 .../features/PolymorphismTest.kt | 0 .../features/PolymorphismWithAnyTest.kt | 1 - .../features/PrimitiveArraySerializersTest.kt | 0 .../features/PropertyInitializerTest.kt | 0 .../SealedClassesSerializationTest.kt | 1 - .../features/SealedPolymorphismTest.kt | 0 .../features/SerializableOnTypeUsageTest.kt | 0 .../features/SerializableWithTest.kt | 0 .../serialization/features/SkipDefaults.kt | 0 .../features/UseSerializersTest.kt | 0 .../inline/EncodeInlineElementTest.kt | 0 .../inline/InlineClassesCompleteTest.kt | 0 .../features/inline/InlineClassesTest.kt | 0 .../features/inline/UnsignedIntegersTest.kt | 0 .../features/sealed/SealedChild.kt | 0 .../features/sealed/SealedParent.kt | 0 .../json/AbstractJsonImplicitNullsTest.kt | 0 .../json/BasicTypesSerializationTest.kt | 0 .../json/DecodeFromJsonElementTest.kt | 0 .../serialization/json/JsonBuildersTest.kt | 0 .../json/JsonCoerceInputValuesTest.kt | 5 +- .../json/JsonConfigurationTest.kt | 0 .../json/JsonCustomSerializersTest.kt | 2 +- .../json/JsonDefaultContextTest.kt | 0 .../json/JsonElementDecodingTest.kt | 0 .../json/JsonEncoderDecoderRecursiveTest.kt | 0 .../serialization/json/JsonGenericTest.kt | 0 .../json/JsonImplicitNullsTest.kt | 0 .../serialization/json/JsonMapKeysTest.kt | 7 +- .../serialization/json/JsonModesTest.kt | 0 .../serialization/json/JsonNumericKeysTest.kt | 0 .../serialization/json/JsonOptionalTests.kt | 0 .../json/JsonParserFailureModesTest.kt | 63 +++++---- .../serialization/json/JsonParserTest.kt | 12 +- .../json/JsonReifiedCollectionsTest.kt | 0 .../json/JsonRootLevelNullTest.kt | 0 .../json/JsonSealedSubclassTest.kt | 0 .../serialization/json/JsonTestBase.kt | 22 ++- .../json/JsonTransformingSerializerTest.kt | 0 .../serialization/json/JsonTransientTest.kt | 3 +- .../json/JsonTreeAndMapperTest.kt | 0 .../json/JsonTreeImplicitNullsTest.kt | 0 .../serialization/json/JsonTreeTest.kt | 1 - .../serialization/json/JsonUnicodeTest.kt | 0 .../serialization/json/JsonUnionEnumTest.kt | 0 .../serialization/json/JsonUpdateModeTest.kt | 0 .../kotlinx/serialization/json/LenientTest.kt | 11 +- .../json/MapLikeSerializerTest.kt | 0 .../json/SpecialFloatingPointValuesTest.kt | 6 +- .../JsonContentPolymorphicSerializerTest.kt | 0 .../JsonDeserializePolymorphicTwiceTest.kt | 0 .../polymorphic/JsonListPolymorphismTest.kt | 0 .../polymorphic/JsonMapPolymorphismTest.kt | 0 .../polymorphic/JsonNestedPolymorphismTest.kt | 0 .../JsonNullablePolymorphicTest.kt | 0 .../JsonPolymorphicClassDescriptorTest.kt | 0 .../polymorphic/JsonPolymorphicObjectTest.kt | 0 .../JsonPolymorphismExceptionTest.kt | 5 +- .../JsonProhibitedPolymorphicKindsTest.kt | 0 .../JsonPropertyPolymorphicTest.kt | 0 .../json/polymorphic/PolymorphicClasses.kt | 0 .../serializers/JsonArraySerializerTest.kt | 21 ++- .../serializers/JsonNativePrimitivesTest.kt | 0 .../serializers/JsonNullSerializerTest.kt | 19 ++- .../serializers/JsonObjectSerializerTest.kt | 125 ++++++++++++++++++ .../JsonPrimitiveSerializerTest.kt | 14 +- .../JsonSerializerInGenericsTest.kt | 0 .../json/serializers/JsonTreeTest.kt | 2 +- .../json/serializers/Primitives.kt | 0 .../SerialNameCollisionInSealedClassesTest.kt | 0 .../modules/SerialNameCollisionTest.kt | 0 .../serialization/test/ContextualTest.kt | 0 .../test/CurrentPlatform.common.kt | 0 .../test/InternalHexConverter.kt | 0 .../kotlinx/serialization/test/JsonHelpers.kt | 0 .../kotlinx/serialization/test/TestHelpers.kt | 0 .../src/kotlinx/serialization/test/TestId.kt | 0 .../serialization/test/TestingFramework.kt | 29 ++++ .../json/DecodeFromDynamicSpecialCasesTest.kt | 0 .../json/DecodeFromDynamicTest.kt | 0 .../json/DynamicPolymorphismTest.kt | 0 .../serialization/json/DynamicToLongTest.kt | 0 .../json/EncodeToDynamicSpecialCasesTest.kt | 5 - .../serialization/json/EncodeToDynamicTest.kt | 0 .../json/JsonCoerceInputValuesDynamicTest.kt | 0 .../json/JsonDynamicImplicitNullsTest.kt | 0 .../json/JsonNamesDynamicTest.kt | 0 .../serialization/test/CurrentPlatform.kt | 0 .../kotlinx/serialization/test/JsonHelpers.kt | 0 .../resources/corner_cases/listing.txt | 0 .../resources/corner_cases/number_1.0.json | 0 .../number_1.000000000000000005.json | 0 .../corner_cases/number_1000000000000000.json | 0 .../number_10000000000000000999.json | 0 .../resources/corner_cases/number_1e-999.json | 0 .../resources/corner_cases/number_1e6.json | 0 .../corner_cases/object_key_nfc_nfd.json | 0 .../corner_cases/object_key_nfd_nfc.json | 0 .../object_same_key_different_values.json | 0 .../object_same_key_same_value.json | 0 .../object_same_key_unclear_values.json | 0 .../string_1_escaped_invalid_codepoint.json | 0 .../string_1_invalid_codepoint.json | 0 .../string_2_escaped_invalid_codepoints.json | 0 .../string_2_invalid_codepoints.json | 0 .../string_3_escaped_invalid_codepoints.json | 0 .../string_3_invalid_codepoints.json | 0 .../string_with_escaped_NULL.json | 0 .../jvmTest/resources/corpus.zip | Bin .../jvmTest/resources/spec_cases/listing.txt | 0 .../n_array_1_true_without_comma.json | 0 .../spec_cases/n_array_a_invalid_utf8.json | 0 .../n_array_colon_instead_of_comma.json | 0 .../spec_cases/n_array_comma_after_close.json | 0 .../spec_cases/n_array_comma_and_number.json | 0 .../spec_cases/n_array_double_comma.json | 0 .../n_array_double_extra_comma.json | 0 .../spec_cases/n_array_extra_close.json | 0 .../spec_cases/n_array_extra_comma.json | 0 .../spec_cases/n_array_incomplete.json | 0 .../n_array_incomplete_invalid_value.json | 0 .../n_array_inner_array_no_comma.json | 0 .../spec_cases/n_array_invalid_utf8.json | 0 .../n_array_items_separated_by_semicolon.json | 0 .../spec_cases/n_array_just_comma.json | 0 .../spec_cases/n_array_just_minus.json | 0 .../spec_cases/n_array_missing_value.json | 0 .../spec_cases/n_array_newlines_unclosed.json | 0 .../spec_cases/n_array_number_and_comma.json | 0 .../n_array_number_and_several_commas.json | 0 .../n_array_spaces_vertical_tab_formfeed.json | 0 .../spec_cases/n_array_star_inside.json | 0 .../spec_cases/n_array_unclosed.json | 0 .../n_array_unclosed_trailing_comma.json | 0 .../n_array_unclosed_with_new_lines.json | 0 .../n_array_unclosed_with_object_inside.json | 0 .../spec_cases/n_incomplete_false.json | 0 .../spec_cases/n_incomplete_null.json | 0 .../spec_cases/n_incomplete_true.json | 0 .../n_multidigit_number_then_00.json | Bin .../spec_cases/n_object_bad_value.json | 0 .../spec_cases/n_object_bracket_key.json | 0 .../n_object_comma_instead_of_colon.json | 0 .../spec_cases/n_object_double_colon.json | 0 .../resources/spec_cases/n_object_emoji.json | 0 .../spec_cases/n_object_garbage_at_end.json | 0 .../n_object_key_with_single_quotes.json | 0 ...uation_byte_in_key_and_trailing_comma.json | 0 .../spec_cases/n_object_missing_colon.json | 0 .../spec_cases/n_object_missing_key.json | 0 .../n_object_missing_semicolon.json | 0 .../spec_cases/n_object_missing_value.json | 0 .../spec_cases/n_object_no-colon.json | 0 .../spec_cases/n_object_non_string_key.json | 0 ...on_string_key_but_huge_number_instead.json | 0 .../n_object_repeated_null_null.json | 0 .../n_object_several_trailing_commas.json | 0 .../spec_cases/n_object_single_quote.json | 0 .../spec_cases/n_object_trailing_comma.json | 0 .../spec_cases/n_object_trailing_comment.json | 0 .../n_object_trailing_comment_open.json | 0 .../n_object_trailing_comment_slash_open.json | 0 ...railing_comment_slash_open_incomplete.json | 0 .../n_object_two_commas_in_a_row.json | 0 .../spec_cases/n_object_unquoted_key.json | 0 .../n_object_unterminated-value.json | 0 .../n_object_with_single_string.json | 0 .../n_object_with_trailing_garbage.json | 0 .../resources/spec_cases/n_single_space.json | 0 .../n_string_1_surrogate_then_escape.json | 0 .../n_string_1_surrogate_then_escape_u.json | 0 .../n_string_1_surrogate_then_escape_u1.json | 0 .../n_string_1_surrogate_then_escape_u1x.json | 0 .../n_string_accentuated_char_no_quotes.json | 0 .../spec_cases/n_string_backslash_00.json | Bin .../spec_cases/n_string_escape_x.json | 0 .../n_string_escaped_backslash_bad.json | 0 .../n_string_escaped_ctrl_char_tab.json | 0 .../spec_cases/n_string_escaped_emoji.json | 0 .../n_string_incomplete_escape.json | 0 ...n_string_incomplete_escaped_character.json | 0 .../n_string_incomplete_surrogate.json | 0 ...g_incomplete_surrogate_escape_invalid.json | 0 .../n_string_invalid-utf-8-in-escape.json | 0 .../n_string_invalid_backslash_esc.json | 0 .../n_string_invalid_unicode_escape.json | 0 .../n_string_invalid_utf8_after_escape.json | 0 .../n_string_leading_uescaped_thinspace.json | 0 .../n_string_no_quotes_with_bad_escape.json | 0 .../n_string_single_doublequote.json | 0 .../spec_cases/n_string_single_quote.json | 0 ...string_single_string_no_double_quotes.json | 0 .../n_string_start_escape_unclosed.json | 0 .../n_string_unescaped_crtl_char.json | Bin .../n_string_unescaped_newline.json | 0 .../spec_cases/n_string_unescaped_tab.json | 0 .../spec_cases/n_string_unicode_CapitalU.json | 0 .../n_string_with_trailing_garbage.json | 0 .../n_structure_100000_opening_arrays.json | 0 .../n_structure_U+2060_word_joined.json | 0 .../n_structure_UTF8_BOM_no_data.json | 0 .../n_structure_angle_bracket_..json | 0 .../n_structure_angle_bracket_null.json | 0 .../n_structure_array_trailing_garbage.json | 0 ...tructure_array_with_extra_array_close.json | 0 ..._structure_array_with_unclosed_string.json | 0 .../n_structure_ascii-unicode-identifier.json | 0 .../n_structure_capitalized_True.json | 0 .../n_structure_close_unopened_array.json | 0 ...ucture_comma_instead_of_closing_brace.json | 0 .../spec_cases/n_structure_double_array.json | 0 .../spec_cases/n_structure_end_array.json | 0 .../n_structure_incomplete_UTF8_BOM.json | 0 .../n_structure_lone-invalid-utf-8.json | 0 .../n_structure_lone-open-bracket.json | 0 .../spec_cases/n_structure_no_data.json | 0 .../n_structure_null-byte-outside-string.json | Bin ...tructure_number_with_trailing_garbage.json | 0 ...ure_object_followed_by_closing_object.json | 0 .../n_structure_object_unclosed_no_value.json | 0 .../n_structure_object_with_comment.json | 0 ...tructure_object_with_trailing_garbage.json | 0 .../n_structure_open_array_apostrophe.json | 0 .../n_structure_open_array_comma.json | 0 .../n_structure_open_array_object.json | 0 .../n_structure_open_array_open_object.json | 0 .../n_structure_open_array_open_string.json | 0 .../n_structure_open_array_string.json | 0 .../spec_cases/n_structure_open_object.json | 0 .../n_structure_open_object_close_array.json | 0 .../n_structure_open_object_comma.json | 0 .../n_structure_open_object_open_array.json | 0 .../n_structure_open_object_open_string.json | 0 ...e_open_object_string_with_apostrophes.json | 0 .../spec_cases/n_structure_open_open.json | 0 .../spec_cases/n_structure_single_star.json | 0 .../spec_cases/n_structure_trailing_#.json | 0 ...n_structure_uescaped_LF_before_string.json | 0 .../n_structure_unclosed_array.json | 0 ...structure_unclosed_array_partial_null.json | 0 ...cture_unclosed_array_unfinished_false.json | 0 ...ucture_unclosed_array_unfinished_true.json | 0 .../n_structure_unclosed_object.json | 0 .../n_structure_unicode-identifier.json | 0 ...ructure_whitespace_U+2060_word_joiner.json | 0 .../n_structure_whitespace_formfeed.json | 0 .../spec_cases/y_array_arraysWithSpaces.json | 0 .../spec_cases/y_array_empty-string.json | 0 .../resources/spec_cases/y_array_empty.json | 0 .../y_array_ending_with_newline.json | 0 .../resources/spec_cases/y_array_false.json | 0 .../spec_cases/y_array_heterogeneous.json | 0 .../resources/spec_cases/y_array_null.json | 0 .../y_array_with_1_and_newline.json | 0 .../y_array_with_leading_space.json | 0 .../spec_cases/y_array_with_several_null.json | 0 .../y_array_with_trailing_space.json | 0 .../resources/spec_cases/y_number.json | 0 .../resources/spec_cases/y_number_0e+1.json | 0 .../resources/spec_cases/y_number_0e1.json | 0 .../spec_cases/y_number_after_space.json | 0 .../y_number_double_close_to_zero.json | 0 .../spec_cases/y_number_int_with_exp.json | 0 .../spec_cases/y_number_minus_zero.json | 0 .../spec_cases/y_number_negative_int.json | 0 .../spec_cases/y_number_negative_one.json | 0 .../spec_cases/y_number_negative_zero.json | 0 .../spec_cases/y_number_real_capital_e.json | 0 .../y_number_real_capital_e_neg_exp.json | 0 .../y_number_real_capital_e_pos_exp.json | 0 .../spec_cases/y_number_real_exponent.json | 0 .../y_number_real_fraction_exponent.json | 0 .../spec_cases/y_number_real_neg_exp.json | 0 .../y_number_real_pos_exponent.json | 0 .../spec_cases/y_number_simple_int.json | 0 .../spec_cases/y_number_simple_real.json | 0 .../resources/spec_cases/y_object.json | 0 .../resources/spec_cases/y_object_basic.json | 0 .../spec_cases/y_object_duplicated_key.json | 0 .../y_object_duplicated_key_and_value.json | 0 .../resources/spec_cases/y_object_empty.json | 0 .../spec_cases/y_object_empty_key.json | 0 .../y_object_escaped_null_in_key.json | 0 .../spec_cases/y_object_extreme_numbers.json | 0 .../spec_cases/y_object_long_strings.json | 0 .../resources/spec_cases/y_object_simple.json | 0 .../spec_cases/y_object_string_unicode.json | 0 .../spec_cases/y_object_with_newlines.json | 0 .../y_string_1_2_3_bytes_UTF-8_sequences.json | 0 .../y_string_accepted_surrogate_pair.json | 0 .../y_string_accepted_surrogate_pairs.json | 0 .../spec_cases/y_string_allowed_escapes.json | 0 ...y_string_backslash_and_u_escaped_zero.json | 0 .../y_string_backslash_doublequotes.json | 0 .../spec_cases/y_string_comments.json | 0 .../spec_cases/y_string_double_escape_a.json | 0 .../spec_cases/y_string_double_escape_n.json | 0 .../y_string_escaped_control_character.json | 0 .../y_string_escaped_noncharacter.json | 0 .../spec_cases/y_string_in_array.json | 0 .../y_string_in_array_with_leading_space.json | 0 .../y_string_last_surrogates_1_and_2.json | 0 .../spec_cases/y_string_nbsp_uescaped.json | 0 ...y_string_nonCharacterInUTF-8_U+10FFFF.json | 0 .../y_string_nonCharacterInUTF-8_U+FFFF.json | 0 .../spec_cases/y_string_null_escape.json | 0 .../spec_cases/y_string_one-byte-utf-8.json | 0 .../resources/spec_cases/y_string_pi.json | 0 ...ring_reservedCharacterInUTF-8_U+1BFFF.json | 0 .../spec_cases/y_string_simple_ascii.json | 0 .../resources/spec_cases/y_string_space.json | 0 ...rogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json | 0 .../spec_cases/y_string_three-byte-utf-8.json | 0 .../spec_cases/y_string_two-byte-utf-8.json | 0 .../spec_cases/y_string_u+2028_line_sep.json | 0 .../spec_cases/y_string_u+2029_par_sep.json | 0 .../spec_cases/y_string_uEscape.json | 0 .../spec_cases/y_string_uescaped_newline.json | 0 .../y_string_unescaped_char_delete.json | 0 .../spec_cases/y_string_unicode.json | 0 .../y_string_unicodeEscapedBackslash.json | 0 .../spec_cases/y_string_unicode_2.json | 0 .../y_string_unicode_U+10FFFE_nonchar.json | 0 .../y_string_unicode_U+1FFFE_nonchar.json | 0 ...tring_unicode_U+200B_ZERO_WIDTH_SPACE.json | 0 ..._string_unicode_U+2064_invisible_plus.json | 0 .../y_string_unicode_U+FDD0_nonchar.json | 0 .../y_string_unicode_U+FFFE_nonchar.json | 0 ...y_string_unicode_escaped_double_quote.json | 0 .../resources/spec_cases/y_string_utf8.json | 0 .../y_string_with_del_character.json | 0 .../spec_cases/y_structure_lonely_false.json | 0 .../spec_cases/y_structure_lonely_int.json | 0 .../y_structure_lonely_negative_real.json | 0 .../spec_cases/y_structure_lonely_null.json | 0 .../spec_cases/y_structure_lonely_string.json | 0 .../spec_cases/y_structure_lonely_true.json | 0 .../spec_cases/y_structure_string_empty.json | 0 .../y_structure_trailing_newline.json | 0 .../spec_cases/y_structure_true_in_array.json | 0 .../y_structure_whitespace_array.json | 0 .../serialization/JavaCollectionsTest.kt | 0 .../JvmMissingFieldsExceptionTest.kt | 1 - .../serialization/SerializationCasesTest.kt | 0 .../serialization/SerializeJavaClassTest.kt | 1 - .../SerializerForNullableJavaTypeTest.kt | 0 .../serialization/StacktraceRecoveryTest.kt | 17 +-- .../ContextualSerializationOnFileTest.kt | 0 .../features/InternalInheritanceTest.kt | 0 .../features/JsonJvmStreamsTest.kt | 0 .../features/JsonLazySequenceTest.kt | 12 +- .../features/JsonSequencePathTest.kt | 8 -- .../features/SerializerByTypeTest.kt | 0 .../json/GsonCompatibilityTest.kt | 0 .../json/ParallelJsonStressTest.kt | 0 .../serialization/json/SpecConformanceTest.kt | Bin .../serialization/test/CurrentPlatform.kt | 0 .../kotlinx/serialization/test/JsonHelpers.kt | 0 .../serialization/json/MultiWorkerJsonTest.kt | 0 .../serialization/test/CurrentPlatform.kt | 0 .../kotlinx/serialization/test/JsonHelpers.kt | 0 .../json/api/kotlinx-serialization-json.api | 73 ++++++++++ formats/json/build.gradle | 11 -- .../kotlinx/serialization/json/JsonElement.kt | 3 +- .../json/internal/StreamingJsonDecoder.kt | 3 +- .../json/internal/TreeJsonDecoder.kt | 3 +- .../json/internal/TreeJsonEncoder.kt | 3 +- .../serialization/json/internal/WriteMode.kt | 3 +- .../json/internal/lexer/AbstractJsonLexer.kt | 59 +++++---- .../lexer/{JsonLexerJvm.kt => JsonLexer.kt} | 13 +- .../json/internal/lexer/StringJsonLexer.kt | 5 +- .../serializers/JsonObjectSerializerTest.kt | 125 ------------------ .../json/internal/DynamicDecoders.kt | 3 +- .../json/internal/JvmJsonStreams.kt | 22 --- settings.gradle | 3 + 409 files changed, 451 insertions(+), 338 deletions(-) create mode 100644 formats/json-tests/build.gradle.kts rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/ClassWithMultipleMasksTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/EncodingCollectionsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/EncodingExtensionsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/GenericSerializersOnFileTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/JsonOverwriteKeyTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/JsonPathTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/NotNullSerializersCompatibilityOnFileTest.kt (96%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/SerializableClasses.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/SerializationForNullableTypeOnFileTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/SerializerForNullableTypeTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/SerializersLookupTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/TuplesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/UmbrellaTypes.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/UnknownElementIndexTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/builtins/KeyValueSerializersTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/BinaryPayloadExampleTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/CollectionSerializerTest.kt (93%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/ContextAndPolymorphicTest.kt (98%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/DerivedContextualSerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/GenericCustomSerializerTest.kt (98%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/InheritanceTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/JsonClassDiscriminatorTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/JsonNamesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/LocalClassesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/LongAsStringTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/ObjectSerialization.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PartiallyCustomSerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PolymorphicOnClassesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt (99%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PrimitiveArraySerializersTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/PropertyInitializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/SealedClassesSerializationTest.kt (99%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/SealedPolymorphismTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/SerializableOnTypeUsageTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/SerializableWithTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/SkipDefaults.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/UseSerializersTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/inline/EncodeInlineElementTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/inline/InlineClassesCompleteTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/inline/InlineClassesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/inline/UnsignedIntegersTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/sealed/SealedChild.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/sealed/SealedParent.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/AbstractJsonImplicitNullsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/BasicTypesSerializationTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/DecodeFromJsonElementTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonBuildersTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonCoerceInputValuesTest.kt (93%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonConfigurationTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt (98%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonDefaultContextTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonElementDecodingTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonEncoderDecoderRecursiveTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonGenericTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonImplicitNullsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonMapKeysTest.kt (93%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonModesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonNumericKeysTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonOptionalTests.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonParserFailureModesTest.kt (53%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt (89%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonReifiedCollectionsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonRootLevelNullTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonSealedSubclassTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt (86%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTransformingSerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTransientTest.kt (94%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTreeImplicitNullsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonTreeTest.kt (99%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonUnicodeTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonUnionEnumTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/JsonUpdateModeTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/LenientTest.kt (84%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/MapLikeSerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/SpecialFloatingPointValuesTest.kt (82%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonContentPolymorphicSerializerTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonDeserializePolymorphicTwiceTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonListPolymorphismTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonMapPolymorphismTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNestedPolymorphismTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonNullablePolymorphicTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicClassDescriptorTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphicObjectTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPolymorphismExceptionTest.kt (88%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonProhibitedPolymorphicKindsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/JsonPropertyPolymorphicTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/polymorphic/PolymorphicClasses.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt (84%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonNativePrimitivesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonNullSerializerTest.kt (69%) create mode 100644 formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonPrimitiveSerializerTest.kt (87%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonSerializerInGenericsTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/JsonTreeTest.kt (99%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/json/serializers/Primitives.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionInSealedClassesTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/modules/SerialNameCollisionTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/ContextualTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/CurrentPlatform.common.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/InternalHexConverter.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/JsonHelpers.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/TestHelpers.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/TestId.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/test/TestingFramework.kt (68%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicSpecialCasesTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/DecodeFromDynamicTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/DynamicPolymorphismTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/EncodeToDynamicSpecialCasesTest.kt (92%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/EncodeToDynamicTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/JsonCoerceInputValuesDynamicTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/JsonDynamicImplicitNullsTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/json/JsonNamesDynamicTest.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/test/CurrentPlatform.kt (100%) rename formats/{json => json-tests}/jsTest/src/kotlinx/serialization/test/JsonHelpers.kt (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/listing.txt (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_1.0.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_1.000000000000000005.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_1000000000000000.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_10000000000000000999.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_1e-999.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/number_1e6.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/object_key_nfc_nfd.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/object_key_nfd_nfc.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/object_same_key_different_values.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/object_same_key_same_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/object_same_key_unclear_values.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_1_escaped_invalid_codepoint.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_1_invalid_codepoint.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_2_escaped_invalid_codepoints.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_2_invalid_codepoints.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_3_escaped_invalid_codepoints.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_3_invalid_codepoints.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corner_cases/string_with_escaped_NULL.json (100%) rename formats/{json => json-tests}/jvmTest/resources/corpus.zip (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/listing.txt (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_1_true_without_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_a_invalid_utf8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_colon_instead_of_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_comma_after_close.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_comma_and_number.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_double_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_double_extra_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_extra_close.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_extra_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_incomplete.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_incomplete_invalid_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_inner_array_no_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_invalid_utf8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_items_separated_by_semicolon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_just_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_just_minus.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_missing_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_newlines_unclosed.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_number_and_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_number_and_several_commas.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_spaces_vertical_tab_formfeed.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_star_inside.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_unclosed.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_unclosed_trailing_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_unclosed_with_new_lines.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_array_unclosed_with_object_inside.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_incomplete_false.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_incomplete_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_incomplete_true.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_multidigit_number_then_00.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_bad_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_bracket_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_comma_instead_of_colon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_double_colon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_emoji.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_garbage_at_end.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_key_with_single_quotes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_lone_continuation_byte_in_key_and_trailing_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_missing_colon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_missing_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_missing_semicolon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_missing_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_no-colon.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_non_string_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_non_string_key_but_huge_number_instead.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_repeated_null_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_several_trailing_commas.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_single_quote.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_trailing_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_trailing_comment.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_trailing_comment_open.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_trailing_comment_slash_open_incomplete.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_two_commas_in_a_row.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_unquoted_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_unterminated-value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_with_single_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_object_with_trailing_garbage.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_single_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_1_surrogate_then_escape_u1x.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_accentuated_char_no_quotes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_backslash_00.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_escape_x.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_escaped_backslash_bad.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_escaped_ctrl_char_tab.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_escaped_emoji.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_incomplete_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_incomplete_escaped_character.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_incomplete_surrogate.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_incomplete_surrogate_escape_invalid.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_invalid-utf-8-in-escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_invalid_backslash_esc.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_invalid_unicode_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_invalid_utf8_after_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_leading_uescaped_thinspace.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_no_quotes_with_bad_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_single_doublequote.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_single_quote.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_single_string_no_double_quotes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_start_escape_unclosed.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_unescaped_crtl_char.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_unescaped_newline.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_unescaped_tab.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_unicode_CapitalU.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_string_with_trailing_garbage.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_100000_opening_arrays.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_U+2060_word_joined.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_UTF8_BOM_no_data.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_angle_bracket_..json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_angle_bracket_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_array_trailing_garbage.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_array_with_extra_array_close.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_array_with_unclosed_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_ascii-unicode-identifier.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_capitalized_True.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_close_unopened_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_comma_instead_of_closing_brace.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_double_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_end_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_incomplete_UTF8_BOM.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_lone-invalid-utf-8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_lone-open-bracket.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_no_data.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_null-byte-outside-string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_number_with_trailing_garbage.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_object_followed_by_closing_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_object_unclosed_no_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_object_with_comment.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_object_with_trailing_garbage.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_apostrophe.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_open_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_open_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_array_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object_close_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object_comma.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object_open_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object_open_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_object_string_with_apostrophes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_open_open.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_single_star.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_trailing_#.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_uescaped_LF_before_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unclosed_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unclosed_array_partial_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_false.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unclosed_array_unfinished_true.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unclosed_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_unicode-identifier.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_whitespace_U+2060_word_joiner.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/n_structure_whitespace_formfeed.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_arraysWithSpaces.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_empty-string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_empty.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_ending_with_newline.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_false.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_heterogeneous.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_with_1_and_newline.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_with_leading_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_with_several_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_array_with_trailing_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_0e+1.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_0e1.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_after_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_double_close_to_zero.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_int_with_exp.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_minus_zero.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_negative_int.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_negative_one.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_negative_zero.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_capital_e.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_capital_e_neg_exp.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_capital_e_pos_exp.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_exponent.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_fraction_exponent.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_neg_exp.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_real_pos_exponent.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_simple_int.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_number_simple_real.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_basic.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_duplicated_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_duplicated_key_and_value.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_empty.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_empty_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_escaped_null_in_key.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_extreme_numbers.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_long_strings.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_simple.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_string_unicode.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_object_with_newlines.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_1_2_3_bytes_UTF-8_sequences.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pair.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_accepted_surrogate_pairs.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_allowed_escapes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_backslash_and_u_escaped_zero.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_backslash_doublequotes.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_comments.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_double_escape_a.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_double_escape_n.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_escaped_control_character.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_escaped_noncharacter.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_in_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_in_array_with_leading_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_last_surrogates_1_and_2.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_nbsp_uescaped.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+10FFFF.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_nonCharacterInUTF-8_U+FFFF.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_null_escape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_one-byte-utf-8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_pi.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_reservedCharacterInUTF-8_U+1BFFF.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_simple_ascii.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_space.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_three-byte-utf-8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_two-byte-utf-8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_u+2028_line_sep.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_u+2029_par_sep.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_uEscape.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_uescaped_newline.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unescaped_char_delete.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicodeEscapedBackslash.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_2.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+10FFFE_nonchar.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+1FFFE_nonchar.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+2064_invisible_plus.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+FDD0_nonchar.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_U+FFFE_nonchar.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_unicode_escaped_double_quote.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_utf8.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_string_with_del_character.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_false.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_int.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_negative_real.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_null.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_string.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_lonely_true.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_string_empty.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_trailing_newline.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_true_in_array.json (100%) rename formats/{json => json-tests}/jvmTest/resources/spec_cases/y_structure_whitespace_array.json (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/JavaCollectionsTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/JvmMissingFieldsExceptionTest.kt (99%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/SerializationCasesTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/SerializeJavaClassTest.kt (98%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/SerializerForNullableJavaTypeTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/StacktraceRecoveryTest.kt (76%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/ContextualSerializationOnFileTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/InternalInheritanceTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/JsonLazySequenceTest.kt (95%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/JsonSequencePathTest.kt (73%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/features/SerializerByTypeTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/json/GsonCompatibilityTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/json/ParallelJsonStressTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/json/SpecConformanceTest.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/test/CurrentPlatform.kt (100%) rename formats/{json => json-tests}/jvmTest/src/kotlinx/serialization/test/JsonHelpers.kt (100%) rename formats/{json => json-tests}/nativeTest/src/kotlinx/serialization/json/MultiWorkerJsonTest.kt (100%) rename formats/{json => json-tests}/nativeTest/src/kotlinx/serialization/test/CurrentPlatform.kt (100%) rename formats/{json => json-tests}/nativeTest/src/kotlinx/serialization/test/JsonHelpers.kt (100%) rename formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/{JsonLexerJvm.kt => JsonLexer.kt} (94%) delete mode 100644 formats/json/commonTest/src/kotlinx/serialization/json/serializers/JsonObjectSerializerTest.kt diff --git a/docs/formats.md b/docs/formats.md index 92f30299a..3c600cc74 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -18,7 +18,6 @@ stable, these are currently experimental features of Kotlin Serialization. * [Integer types](#integer-types) * [Lists as repeated fields](#lists-as-repeated-fields) * [Packed fields](#packed-fields) - * [ProtoBuf schema generator (experimental)](#protobuf-schema-generator-experimental) * [Properties (experimental)](#properties-experimental) * [Custom formats (experimental)](#custom-formats-experimental) * [Basic encoder](#basic-encoder) diff --git a/docs/serialization-guide.md b/docs/serialization-guide.md index 3506fcf06..46a54d21b 100644 --- a/docs/serialization-guide.md +++ b/docs/serialization-guide.md @@ -115,7 +115,7 @@ Once the project is set up, we can start serializing some classes. * [Explicit nulls](json.md#explicit-nulls) * [Allowing structured map keys](json.md#allowing-structured-map-keys) * [Allowing special floating-point values](json.md#allowing-special-floating-point-values) - * [Class discriminator](json.md#class-discriminator) + * [Class discriminator for polymorphism](json.md#class-discriminator-for-polymorphism) * [Json elements](json.md#json-elements) * [Parsing to Json element](json.md#parsing-to-json-element) * [Types of Json elements](json.md#types-of-json-elements) @@ -140,6 +140,7 @@ Once the project is set up, we can start serializing some classes. * [Field numbers](formats.md#field-numbers) * [Integer types](formats.md#integer-types) * [Lists as repeated fields](formats.md#lists-as-repeated-fields) + * [Packed fields](formats.md#packed-fields) * [Properties (experimental)](formats.md#properties-experimental) * [Custom formats (experimental)](formats.md#custom-formats-experimental) * [Basic encoder](formats.md#basic-encoder) diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts new file mode 100644 index 000000000..5d21ed902 --- /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")) + +// disable kover tasks because there are no non-test classes in the project +tasks.koverHtmlReport { + enabled = false +} +tasks.koverXmlReport { + enabled = false +} +tasks.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:3.1.0") + } + } + + val jvmTest by getting { + dependencies { + implementation("com.google.code.gson:gson:2.8.5") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${property("coroutines_version")}") + } + } + } +} + +tasks.withType { + if (this.name == "compileTestKotlinJsLegacy") { + this.exclude("**/PropertyInitializerTest.kt") + } +} + +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/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/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/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/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 89% 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..8062f4dda 100644 --- a/formats/json/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt @@ -30,14 +30,14 @@ class JsonParserTest : JsonTestBase() { @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 86% 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..6e23b896f 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.decodeFromOkio +import kotlinx.serialization.json.okio.encodeToOkio 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() + encodeToOkio(serializer, value, buffer) + buffer.readUtf8() + } } internal inline fun Json.decodeFromString(source: String, jsonTestingMode: JsonTestingMode): T { @@ -72,12 +82,19 @@ abstract class JsonTestBase { lexer.expectEof() readJson(tree, deserializer) } + JsonTestingMode.OKIO_STREAMS -> { + val buffer = Buffer() + buffer.writeUtf8(source) + decodeFromOkio(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 +118,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 84% 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..266e9e975 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,20 +26,20 @@ 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) 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 100% rename from formats/json/commonTest/src/kotlinx/serialization/test/TestHelpers.kt rename to formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt 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..093763a2f 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 message '${exception.message}' to contain substring '$message'" + ) + 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 100% rename from formats/json/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt rename to formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt 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 100% rename from formats/json/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt rename to formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt 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 e7dbc27d6..7aa302c1b 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -232,6 +232,14 @@ public final class kotlinx/serialization/json/JsonKt { public static synthetic fun Json$default (Lkotlinx/serialization/json/Json;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/serialization/json/Json; } +public final class kotlinx/serialization/json/JsonLiteral : kotlinx/serialization/json/JsonPrimitive { + public fun equals (Ljava/lang/Object;)Z + public fun getContent ()Ljava/lang/String; + public fun hashCode ()I + public fun isString ()Z + public fun toString ()Ljava/lang/String; +} + public abstract interface annotation class kotlinx/serialization/json/JsonNames : java/lang/annotation/Annotation { public abstract fun names ()[Ljava/lang/String; } @@ -358,6 +366,24 @@ 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 abstract class kotlinx/serialization/json/internal/AbstractJsonLexer { + protected field currentPosition I + public fun ()V + protected fun appendRange (II)V + protected final fun consumeString (Ljava/lang/CharSequence;II)Ljava/lang/String; + public final fun expectEof ()V + protected final fun getEscapedString ()Ljava/lang/StringBuilder; + protected abstract fun getSource ()Ljava/lang/CharSequence; + protected final fun isValidValueStart (C)Z + protected final fun setEscapedString (Ljava/lang/StringBuilder;)V + public fun toString ()Ljava/lang/String; + protected final fun unexpectedToken (C)V +} + +public final class kotlinx/serialization/json/internal/JsonLexerKt { + public static final field BATCH_SIZE I +} + 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 decodeToSequence (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/SerialReader;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; @@ -377,8 +403,55 @@ public abstract interface class kotlinx/serialization/json/internal/SerialReader public abstract fun read ([CII)I } +public class kotlinx/serialization/json/internal/StreamingJsonDecoder : kotlinx/serialization/encoding/AbstractDecoder, kotlinx/serialization/json/JsonDecoder { + public fun (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/WriteMode;Lkotlinx/serialization/json/internal/AbstractJsonLexer;Lkotlinx/serialization/descriptors/SerialDescriptor;)V + public fun beginStructure (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder; + public fun decodeBoolean ()Z + public fun decodeByte ()B + public fun decodeChar ()C + public fun decodeDouble ()D + public fun decodeElementIndex (Lkotlinx/serialization/descriptors/SerialDescriptor;)I + public fun decodeEnum (Lkotlinx/serialization/descriptors/SerialDescriptor;)I + public fun decodeFloat ()F + public fun decodeInline (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/Decoder; + public fun decodeInt ()I + public fun decodeJsonElement ()Lkotlinx/serialization/json/JsonElement; + public fun decodeLong ()J + public fun decodeNotNullMark ()Z + public fun decodeNull ()Ljava/lang/Void; + public fun decodeSerializableElement (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object; + public fun decodeSerializableValue (Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object; + public fun decodeShort ()S + public fun decodeString ()Ljava/lang/String; + public fun endStructure (Lkotlinx/serialization/descriptors/SerialDescriptor;)V + public final fun getJson ()Lkotlinx/serialization/json/Json; + public fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule; +} + +public final class kotlinx/serialization/json/internal/StringJsonLexer : kotlinx/serialization/json/internal/AbstractJsonLexer { + public fun (Ljava/lang/String;)V + public synthetic fun getSource ()Ljava/lang/CharSequence; +} + public final class kotlinx/serialization/json/internal/StringOpsKt { public static final fun getESCAPE_MARKERS ()[B public static final fun getESCAPE_STRINGS ()[Ljava/lang/String; } +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; +} + +public final class kotlinx/serialization/json/internal/WriteMode : java/lang/Enum { + public static final field LIST Lkotlinx/serialization/json/internal/WriteMode; + public static final field MAP Lkotlinx/serialization/json/internal/WriteMode; + public static final field OBJ Lkotlinx/serialization/json/internal/WriteMode; + public static final field POLY_OBJ Lkotlinx/serialization/json/internal/WriteMode; + public static fun valueOf (Ljava/lang/String;)Lkotlinx/serialization/json/internal/WriteMode; + public static fun values ()[Lkotlinx/serialization/json/internal/WriteMode; +} + diff --git a/formats/json/build.gradle b/formats/json/build.gradle index 229444598..ec066ee94 100644 --- a/formats/json/build.gradle +++ b/formats/json/build.gradle @@ -15,18 +15,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/JsonElement.kt b/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt index 07b5973a3..8cb4b6013 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt @@ -77,7 +77,8 @@ public fun JsonPrimitive(value: String?): JsonPrimitive { public fun JsonPrimitive(value: Nothing?): JsonNull = JsonNull // JsonLiteral is deprecated for public use and no longer available. Please use JsonPrimitive instead -internal class JsonLiteral internal constructor( +@InternalSerializationApi +public class JsonLiteral internal constructor( body: Any, public override val isString: Boolean ) : JsonPrimitive() { 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..528efa37c 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt @@ -18,7 +18,8 @@ import kotlin.jvm.* * [JsonDecoder] which reads given JSON from [AbstractJsonLexer] field by field. */ @OptIn(ExperimentalSerializationApi::class) -internal open class StreamingJsonDecoder( +@InternalSerializationApi +public open class StreamingJsonDecoder( final override val json: Json, private val mode: WriteMode, @JvmField internal val lexer: AbstractJsonLexer, 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/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt index 382d8bce4..1341499cd 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt @@ -11,7 +11,8 @@ import kotlinx.serialization.json.* import kotlinx.serialization.modules.* import kotlin.jvm.* -internal enum class WriteMode(@JvmField val begin: Char, @JvmField val end: Char) { +@InternalSerializationApi +public enum class WriteMode(@JvmField internal val begin: Char, @JvmField internal val end: Char) { OBJ(BEGIN_OBJ, END_OBJ), LIST(BEGIN_LIST, END_LIST), MAP(BEGIN_OBJ, END_OBJ), diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt index 977347a55..aacc69e15 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt @@ -4,7 +4,7 @@ package kotlinx.serialization.json.internal -import kotlinx.serialization.json.internal.* +import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.json.internal.CharMappings.CHAR_TO_TOKEN import kotlinx.serialization.json.internal.CharMappings.ESCAPE_2_CHAR import kotlin.js.* @@ -130,7 +130,8 @@ internal fun escapeToChar(c: Int): Char = if (c < ESC2C_MAX) ESCAPE_2_CHAR[c] el * of them for the performance reasons (devirtualization of [CharSequence] and avoid * of additional spills). */ -internal abstract class AbstractJsonLexer { +@InternalSerializationApi +public abstract class AbstractJsonLexer { protected abstract val source: CharSequence @@ -138,20 +139,20 @@ internal abstract class AbstractJsonLexer { protected var currentPosition: Int = 0 // position in source @JvmField - val path = JsonPath() + internal val path = JsonPath() - open fun ensureHaveChars() {} + internal open fun ensureHaveChars() {} - fun isNotEof(): Boolean = peekNextToken() != TC_EOF + internal fun isNotEof(): Boolean = peekNextToken() != TC_EOF // Used as bound check in loops - abstract fun prefetchOrEof(position: Int): Int + internal abstract fun prefetchOrEof(position: Int): Int - abstract fun tryConsumeComma(): Boolean + internal abstract fun tryConsumeComma(): Boolean - abstract fun canConsumeValue(): Boolean + internal abstract fun canConsumeValue(): Boolean - abstract fun consumeNextToken(): Byte + internal abstract fun consumeNextToken(): Byte protected fun isValidValueStart(c: Char): Boolean { return when (c) { @@ -160,7 +161,7 @@ internal abstract class AbstractJsonLexer { } } - fun expectEof() { + public fun expectEof() { val nextToken = consumeNextToken() if (nextToken != TC_EOF) fail("Expected EOF after parsing, but had ${source[currentPosition - 1]} instead") @@ -171,10 +172,10 @@ internal abstract class AbstractJsonLexer { * If the value was picked, 'consumeString' will take it without scanning the source. */ private var peekedString: String? = null - protected var escapedString = StringBuilder() + protected var escapedString: StringBuilder = StringBuilder() // TODO consider replacing usages of this method in JsonParser with char overload - fun consumeNextToken(expected: Byte): Byte { + internal fun consumeNextToken(expected: Byte): Byte { val token = consumeNextToken() if (token != expected) { fail(expected) @@ -182,7 +183,7 @@ internal abstract class AbstractJsonLexer { return token } - open fun consumeNextToken(expected: Char) { + internal open fun consumeNextToken(expected: Char) { ensureHaveChars() val source = source var cpos = currentPosition @@ -224,7 +225,7 @@ internal abstract class AbstractJsonLexer { fail("Expected $expected, but had '$s' instead", currentPosition - 1) } - fun peekNextToken(): Byte { + internal fun peekNextToken(): Byte { val source = source var cpos = currentPosition while (true) { @@ -247,7 +248,7 @@ internal abstract class AbstractJsonLexer { * Returns `true` if the next 4 chars in input are not `null`, * `false` otherwise and consumes it. */ - fun tryConsumeNotNull(): Boolean { + internal fun tryConsumeNotNull(): Boolean { var current = skipWhitespaces() current = prefetchOrEof(current) // Cannot consume null due to EOF, maybe something else @@ -265,7 +266,7 @@ internal abstract class AbstractJsonLexer { return false } - open fun skipWhitespaces(): Int { + internal open fun skipWhitespaces(): Int { var current = currentPosition // Skip whitespaces while (true) { @@ -285,7 +286,7 @@ internal abstract class AbstractJsonLexer { abstract fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? - fun peekString(isLenient: Boolean): String? { + internal fun peekString(isLenient: Boolean): String? { val token = peekNextToken() val string = if (isLenient) { if (token != TC_STRING && token != TC_OTHER) return null @@ -298,16 +299,16 @@ internal abstract class AbstractJsonLexer { return string } - open fun indexOf(char: Char, startPos: Int) = source.indexOf(char, startPos) - open fun substring(startPos: Int, endPos: Int) = source.substring(startPos, endPos) + internal open fun indexOf(char: Char, startPos: Int) = source.indexOf(char, startPos) + internal open fun substring(startPos: Int, endPos: Int) = source.substring(startPos, endPos) /* * This method is a copy of consumeString, but used for key of json objects, so there * is no need to lookup peeked string. */ - abstract fun consumeKeyString(): String + internal abstract fun consumeKeyString(): String - fun consumeString(): String { + internal fun consumeString(): String { if (peekedString != null) { return takePeeked() } @@ -367,7 +368,7 @@ internal abstract class AbstractJsonLexer { return peekedString!!.also { peekedString = null } } - fun consumeStringLenientNotNull(): String { + internal fun consumeStringLenientNotNull(): String { val result = consumeStringLenient() /* * Check if lenient value is 'null' _without_ quotation marks and fail for non-nullable read if so. @@ -384,7 +385,7 @@ internal abstract class AbstractJsonLexer { } // Allows consuming unquoted string - fun consumeStringLenient(): String { + internal fun consumeStringLenient(): String { if (peekedString != null) { return takePeeked() } @@ -473,7 +474,7 @@ internal abstract class AbstractJsonLexer { } } - fun skipElement(allowLenientStrings: Boolean) { + internal fun skipElement(allowLenientStrings: Boolean) { val tokenStack = mutableListOf() var lastToken = peekNextToken() if (lastToken != TC_BEGIN_LIST && lastToken != TC_BEGIN_OBJ) { @@ -517,7 +518,7 @@ internal abstract class AbstractJsonLexer { return "JsonReader(source='$source', currentPosition=$currentPosition)" } - fun failOnUnknownKey(key: String) { + internal fun failOnUnknownKey(key: String) { // At this moment we already have both key and semicolon (and whitespaces! consumed), // but still would like an error to point to the beginning of the key, so we are backtracking it val processed = substring(0, currentPosition) @@ -525,12 +526,12 @@ internal abstract class AbstractJsonLexer { fail("Encountered an unknown key '$key'", lastIndexOf, ignoreUnknownKeysHint) } - fun fail(message: String, position: Int = currentPosition, hint: String = ""): Nothing { + internal fun fail(message: String, position: Int = currentPosition, hint: String = ""): Nothing { val hintMessage = if (hint.isEmpty()) "" else "\n$hint" throw JsonDecodingException(position, message + " at path: " + path.getPath() + hintMessage, source) } - fun consumeNumericLiteral(): Long { + internal fun consumeNumericLiteral(): Long { /* * This is an optimized (~40% for numbers) version of consumeString().toLong() * that doesn't allocate and also doesn't support any radix but 10 @@ -584,11 +585,11 @@ internal abstract class AbstractJsonLexer { } - fun consumeBoolean(): Boolean { + internal fun consumeBoolean(): Boolean { return consumeBoolean(skipWhitespaces()) } - fun consumeBooleanLenient(): Boolean { + internal fun consumeBooleanLenient(): Boolean { var current = skipWhitespaces() if (current == source.length) fail("EOF") val hasQuotation = if (source[current] == STRING) { diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt similarity index 94% rename from formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt rename to formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt index 5e2683022..ba5bf7518 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexerJvm.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt @@ -4,14 +4,11 @@ package kotlinx.serialization.json.internal -internal const val BATCH_SIZE = 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 +import kotlinx.serialization.InternalSerializationApi +@InternalSerializationApi +public const val BATCH_SIZE: Int = 16 * 1024 +private const val DEFAULT_THRESHOLD = 128 /** * For some reason this hand-rolled implementation is faster than @@ -167,7 +164,7 @@ internal class ReaderJsonLexer( } 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/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt index 9ccfbcc1d..40ac6f61e 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt @@ -4,7 +4,10 @@ package kotlinx.serialization.json.internal -internal class StringJsonLexer(override val source: String) : AbstractJsonLexer() { +import kotlinx.serialization.InternalSerializationApi + +@InternalSerializationApi +public class StringJsonLexer(override val source: String) : AbstractJsonLexer() { override fun prefetchOrEof(position: Int): Int = if (position < source.length) position else -1 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/DynamicDecoders.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt index a6658c7cb..1bc825a50 100644 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt +++ b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt @@ -15,7 +15,8 @@ import kotlin.math.* /** * [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 +@InternalSerializationApi +public const val MAX_SAFE_INTEGER: Double = 9007199254740991.toDouble() // 2^53 - 1 @JsName("decodeDynamic") internal fun Json.decodeDynamic(deserializer: DeserializationStrategy, dynamic: dynamic): T { diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt index b10c86ee8..4bf0c4f32 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt @@ -98,28 +98,6 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr return oldSize } -// override fun writeQuoted(text: String) { -// val escapeStrings = ESCAPE_STRINGS -// val length = text.length -// -// writeUtf8CodePoint(DOUBLE_QUOTES_CODE) -// var lastPos = 0 -// for (i in 0 until length) { -// val c = text[i].code -// if (c < escapeStrings.size) { -// escapeStrings[c]?.let { -// writeUtf8(text, lastPos, i) // flush prev -// writeUtf8(it) -// lastPos = i + 1 -// } -// } -// } -// -// if (lastPos != 0) writeUtf8(text, lastPos, length) -// else writeUtf8(text) -// writeUtf8CodePoint(DOUBLE_QUOTES_CODE) -// } - override fun release() { flush() CharArrayPool.release(array) diff --git a/settings.gradle b/settings.gradle index f6472f1a1..01d4ea62f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,6 +16,9 @@ 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') From 15fc853c75d721095e42a4cb8ae2a13cfbfb171b Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Thu, 19 May 2022 12:29:32 +0300 Subject: [PATCH 12/27] Revert docs changes --- docs/formats.md | 77 +++++++++++++++++++++++++++++++++---- docs/serialization-guide.md | 1 + 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/docs/formats.md b/docs/formats.md index 3c600cc74..288981e3f 100644 --- a/docs/formats.md +++ b/docs/formats.md @@ -18,6 +18,7 @@ stable, these are currently experimental features of Kotlin Serialization. * [Integer types](#integer-types) * [Lists as repeated fields](#lists-as-repeated-fields) * [Packed fields](#packed-fields) + * [ProtoBuf schema generator (experimental)](#protobuf-schema-generator-experimental) * [Properties (experimental)](#properties-experimental) * [Custom formats (experimental)](#custom-formats-experimental) * [Basic encoder](#basic-encoder) @@ -434,6 +435,62 @@ Per the standard packed fields can only be used on primitive numeric types. The Per the [format description](https://developers.google.com/protocol-buffers/docs/encoding#packed) the parser ignores the annotation, but rather reads list in either packed or repeated format. +### ProtoBuf schema generator (experimental) + +As mentioned above, when working with protocol buffers you usually use a ".proto" file and a code generator for your +language. This includes the code to serialize your message to an output stream and deserialize it from an input stream. +When using Kotlin Serialization this step is not necessary because your `@Serializable` Kotlin data types are used as the +source for the schema. + +This is very convenient for Kotlin-to-Kotlin communication, but makes interoperability between languages complicated. +Fortunately, you can use the ProtoBuf schema generator to output the ".proto" representation of your messages. You can +keep your Kotlin classes as a source of truth and use traditional protoc compilers for other languages at the same time. + +As an example, we can display the following data class's ".proto" schema as follows. + + + +```kotlin +@Serializable +data class SampleData( + val amount: Long, + val description: String?, + val department: String = "QA" +) +fun main() { + val descriptors = listOf(SampleData.serializer().descriptor) + val schemas = ProtoBufSchemaGenerator.generateSchemaText(descriptors) + println(schemas) +} +``` +> You can get the full code [here](../guide/example/example-formats-08.kt). + +Which would output as follows. + +```text +syntax = "proto2"; + + +// serial name 'example.exampleFormats08.SampleData' +message SampleData { + required int64 amount = 1; + optional string description = 2; + // WARNING: a default value decoded when value is missing + optional string department = 3; +} + +``` + + + +Note that since default values are not represented in ".proto" files, a warning is generated when one appears in the schema. + +See the documentation for [ProtoBufSchemaGenerator] for more information. + ## Properties (experimental) Kotlin Serialization can serialize a class into a flat map with `String` keys via @@ -462,7 +519,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-08.kt). +> You can get the full code [here](../guide/example/example-formats-09.kt). The resulting map has dot-separated keys representing keys of the nested objects. @@ -542,7 +599,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-09.kt). +> You can get the full code [here](../guide/example/example-formats-10.kt). As a result, we got all the primitive values in our object graph visited and put into a list in _serial_ order. @@ -644,7 +701,7 @@ fun main() { } ``` -> You can get the full code [here](../guide/example/example-formats-10.kt). +> You can get the full code [here](../guide/example/example-formats-11.kt). Now we can convert a list of primitives back to an object tree. @@ -735,7 +792,7 @@ fun main() { } --> -> You can get the full code [here](../guide/example/example-formats-11.kt). +> You can get the full code [here](../guide/example/example-formats-12.kt). + +[ProtoBufSchemaGenerator]: https://kotlin.github.io/kotlinx.serialization/kotlinx-serialization-protobuf/kotlinx.serialization.protobuf.schema/-proto-buf-schema-generator/index.html + diff --git a/docs/serialization-guide.md b/docs/serialization-guide.md index 46a54d21b..e3f28eae7 100644 --- a/docs/serialization-guide.md +++ b/docs/serialization-guide.md @@ -141,6 +141,7 @@ Once the project is set up, we can start serializing some classes. * [Integer types](formats.md#integer-types) * [Lists as repeated fields](formats.md#lists-as-repeated-fields) * [Packed fields](formats.md#packed-fields) + * [ProtoBuf schema generator (experimental)](formats.md#protobuf-schema-generator-experimental) * [Properties (experimental)](formats.md#properties-experimental) * [Custom formats (experimental)](formats.md#custom-formats-experimental) * [Basic encoder](formats.md#basic-encoder) From c17ae93ea95e06ddb895b051b7d99305a664c478 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Thu, 19 May 2022 12:35:24 +0300 Subject: [PATCH 13/27] Mark json-tests as multiplatform --- gradle/publishing.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle index 740b5c632..912050cef 100644 --- a/gradle/publishing.gradle +++ b/gradle/publishing.gradle @@ -10,7 +10,8 @@ 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-json-okio", - "kotlinx-serialization-protobuf", "kotlinx-serialization-cbor", "kotlinx-serialization-properties"] + "kotlinx-serialization-json-tests", "kotlinx-serialization-protobuf", "kotlinx-serialization-cbor", + "kotlinx-serialization-properties"] def isBom = project.name == "kotlinx-serialization-bom" if (!isBom) { From b1ed21a55288b88509b3d05deb4f8db595f4fd93 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 22 Jun 2022 15:56:15 +0300 Subject: [PATCH 14/27] rebase fixes --- formats/json-tests/build.gradle.kts | 12 ++++++------ .../kotlinx/serialization/features/DurationTest.kt | 0 .../features/inline/InlineMapQuotedTest.kt | 0 .../features/sealed/SealedDiamondTest.kt | 0 .../sealed/SealedInterfacesJsonSerializationTest.kt | 0 5 files changed, 6 insertions(+), 6 deletions(-) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/DurationTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/inline/InlineMapQuotedTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/sealed/SealedDiamondTest.kt (100%) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt (100%) diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts index 5d21ed902..6474dc9fa 100644 --- a/formats/json-tests/build.gradle.kts +++ b/formats/json-tests/build.gradle.kts @@ -11,6 +11,12 @@ plugins { 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.koverHtmlReport { enabled = false @@ -41,10 +47,4 @@ kotlin { } } -tasks.withType { - if (this.name == "compileTestKotlinJsLegacy") { - this.exclude("**/PropertyInitializerTest.kt") - } -} - project.configureJava9ModuleInfo() 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/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/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 From d78e98a2a0eb557ea81ea96b4caa495879b9f5c6 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 22 Jun 2022 16:11:16 +0300 Subject: [PATCH 15/27] excluded targets for project with JSON tests --- gradle/native-targets.gradle | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gradle/native-targets.gradle b/gradle/native-targets.gradle index 17bcaac32..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,7 +97,7 @@ kotlin { } else { // Linux addTarget(presets.linuxX64) - if (!project.name.contains("json-okio")) { + if (doesNotDependOnOkio(project)) { addTarget(presets.linuxArm32Hfp) addTarget(presets.linuxArm64) } @@ -102,7 +106,7 @@ kotlin { addTarget(presets.macosX64) addTarget(presets.iosArm64) - if (!project.name.contains("json-okio")) { + if (doesNotDependOnOkio(project)) { addTarget(presets.iosArm32) } addTarget(presets.iosX64) @@ -123,7 +127,7 @@ kotlin { // Windows addTarget(presets.mingwX64) - if (!project.name.contains("json-okio")) { + if (doesNotDependOnOkio(project)) { addTarget(presets.mingwX86) } } From 9b14d52be51132062c51db6348e768607363d4b8 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 22 Jun 2022 16:53:41 +0300 Subject: [PATCH 16/27] Removed publication of project with JSON tests --- build.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f696639fc..6e66ea672 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') } @@ -163,7 +165,7 @@ subprojects { subprojects { // Can't be applied to BOM - if (project.name == "kotlinx-serialization-bom" || project.name == "benchmark" || project.name == "guide") return + if (project.name == "kotlinx-serialization-bom" || unpublishedProjects.contains(project.name)) return // Animalsniffer setup apply plugin: 'ru.vyarus.animalsniffer' From cd6a69b4ba4d244974308dd9f8349544bf2cbbe9 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 22 Jun 2022 17:07:14 +0300 Subject: [PATCH 17/27] fixes --- formats/json-tests/build.gradle.kts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts index 6474dc9fa..3b722f898 100644 --- a/formats/json-tests/build.gradle.kts +++ b/formats/json-tests/build.gradle.kts @@ -17,17 +17,6 @@ tasks.withType { } } -// disable kover tasks because there are no non-test classes in the project -tasks.koverHtmlReport { - enabled = false -} -tasks.koverXmlReport { - enabled = false -} -tasks.koverVerify { - enabled = false -} - kotlin { sourceSets { val commonTest by getting { From 0670aff89bc22fb973ec1fd533a8d9dab0799887 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Sat, 25 Jun 2022 12:22:30 +0300 Subject: [PATCH 18/27] merge fixes --- .../features/DefaultPolymorphicSerializerTest.kt | 3 ++- formats/json/api/kotlinx-serialization-json.api | 7 ++++++- .../src/kotlinx/serialization/json/internal/JsonStreams.kt | 2 +- .../serialization/json/internal/StreamingJsonDecoder.kt | 2 +- .../serialization/json/internal/lexer/AbstractJsonLexer.kt | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) rename formats/{json => json-tests}/commonTest/src/kotlinx/serialization/features/DefaultPolymorphicSerializerTest.kt (92%) 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/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index 7aa302c1b..fd1c624ce 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -404,7 +404,7 @@ public abstract interface class kotlinx/serialization/json/internal/SerialReader } public class kotlinx/serialization/json/internal/StreamingJsonDecoder : kotlinx/serialization/encoding/AbstractDecoder, kotlinx/serialization/json/JsonDecoder { - public fun (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/WriteMode;Lkotlinx/serialization/json/internal/AbstractJsonLexer;Lkotlinx/serialization/descriptors/SerialDescriptor;)V + public fun (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/WriteMode;Lkotlinx/serialization/json/internal/AbstractJsonLexer;Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlinx/serialization/json/internal/StreamingJsonDecoder$DiscriminatorHolder;)V public fun beginStructure (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder; public fun decodeBoolean ()Z public fun decodeByte ()B @@ -428,6 +428,11 @@ public class kotlinx/serialization/json/internal/StreamingJsonDecoder : kotlinx/ public fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule; } +public final class kotlinx/serialization/json/internal/StreamingJsonDecoder$DiscriminatorHolder { + public field discriminatorToSkip Ljava/lang/String; + public fun (Ljava/lang/String;)V +} + public final class kotlinx/serialization/json/internal/StringJsonLexer : kotlinx/serialization/json/internal/AbstractJsonLexer { public fun (Ljava/lang/String;)V public synthetic fun getSource ()Ljava/lang/CharSequence; diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt index 4fab95a80..d3616bc76 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt @@ -39,7 +39,7 @@ public fun Json.decodeByReader( reader: SerialReader ): T { val lexer = ReaderJsonLexer(reader) - val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor) + val input = StreamingJsonDecoder(this, WriteMode.OBJ, lexer, deserializer.descriptor, null) val result = input.decodeSerializableValue(deserializer) lexer.expectEof() return result 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 528efa37c..62c7c198e 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt @@ -29,7 +29,7 @@ public open class StreamingJsonDecoder( // A mutable reference to the discriminator that have to be skipped when in optimistic phase // of polymorphic serialization, see `decodeSerializableValue` - internal class DiscriminatorHolder(@JvmField var discriminatorToSkip: String?) + public class DiscriminatorHolder(@JvmField public var discriminatorToSkip: String?) private fun DiscriminatorHolder?.trySkip(unknownKey: String): Boolean { if (this == null) return false diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt index aacc69e15..c2d8fc5f6 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt @@ -284,7 +284,7 @@ public abstract class AbstractJsonLexer { return current } - abstract fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? + internal abstract fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? internal fun peekString(isLenient: Boolean): String? { val token = peekNextToken() From bf38cdb05123018cdfc7dfed0246f4198cad522c Mon Sep 17 00:00:00 2001 From: Sergey Shanshin Date: Tue, 28 Jun 2022 22:41:48 +0300 Subject: [PATCH 19/27] Update formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt Co-authored-by: Leonid Startsev --- .../src/kotlinx/serialization/json/okio/OkioStreams.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index ddf21da85..0f15377aa 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -34,7 +34,7 @@ public fun Json.encodeToOkio( } /** - * Serializes given [value] to [target] using UTF-8 encoding and serializer retrieved from the reified type parameter. + * Serializes given [value] to a [target] using UTF-8 encoding and serializer retrieved from the reified type parameter. * * @throws [SerializationException] if the given value cannot be serialized to JSON. */ From 9330a334c8f4cc4737ac776df05d0361964c1bac Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 00:28:20 +0300 Subject: [PATCH 20/27] review fixes --- build.gradle | 2 +- .../api/kotlinx-serialization-json-okio.api | 8 +- formats/json-okio/build.gradle.kts | 4 +- .../serialization/json/okio/OkioStreams.kt | 46 ++++++------ .../serialization/json/okio/TestTest.kt | 57 -------------- formats/json-tests/build.gradle.kts | 15 +++- .../serialization/json/JsonTestBase.kt | 13 ++-- .../serialization/test/TestingFramework.kt | 2 +- .../serialization/json/DynamicToLongTest.kt | 6 +- .../features/JsonJvmStreamsTest.kt | 5 ++ .../json/api/kotlinx-serialization-json.api | 62 +-------------- .../src/kotlinx/serialization/json/Json.kt | 2 +- .../json/internal/JsonStreams.kt | 6 +- .../json/internal/StreamingJsonDecoder.kt | 15 +++- .../serialization/json/internal/StringOps.kt | 2 + .../serialization/json/internal/WriteMode.kt | 3 +- .../json/internal/lexer/AbstractJsonLexer.kt | 61 ++++++++------- .../json/internal/lexer/StringJsonLexer.kt | 5 +- .../json/internal/DynamicDecoders.kt | 3 +- .../kotlinx/serialization/json/JvmStreams.kt | 2 +- .../json/internal/JvmJsonStreams.kt | 75 +++++++++---------- gradle.properties | 1 + 22 files changed, 150 insertions(+), 245 deletions(-) delete mode 100644 formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt diff --git a/build.gradle b/build.gradle index 6e66ea672..15dd39795 100644 --- a/build.gradle +++ b/build.gradle @@ -165,7 +165,7 @@ subprojects { subprojects { // Can't be applied to BOM - if (project.name == "kotlinx-serialization-bom" || unpublishedProjects.contains(project.name)) return + if (project.name == "kotlinx-serialization-bom" || project.name == "benchmark" || project.name == "guide") return // Animalsniffer setup apply plugin: 'ru.vyarus.animalsniffer' diff --git a/formats/json-okio/api/kotlinx-serialization-json-okio.api b/formats/json-okio/api/kotlinx-serialization-json-okio.api index 234bea703..75effa13f 100644 --- a/formats/json-okio/api/kotlinx-serialization-json-okio.api +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -1,7 +1,7 @@ public final class kotlinx/serialization/json/okio/OkioStreamsKt { - public static final fun decodeFromOkio (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; - public static final fun decodeOkioToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; - public static synthetic fun decodeOkioToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; - public static final fun encodeToOkio (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/BufferedSink;)V + public static final fun decodeBufferedSourceToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; + public static synthetic fun decodeBufferedSourceToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; + public static final fun decodeFromBufferedSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; + public static final fun encodeToBufferedSink (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/BufferedSink;)V } diff --git a/formats/json-okio/build.gradle.kts b/formats/json-okio/build.gradle.kts index 9cdc4afe6..3e6565e9e 100644 --- a/formats/json-okio/build.gradle.kts +++ b/formats/json-okio/build.gradle.kts @@ -17,12 +17,12 @@ kotlin { dependencies { api(project(":kotlinx-serialization-core")) api(project(":kotlinx-serialization-json")) - implementation("com.squareup.okio:okio:3.1.0") + implementation("com.squareup.okio:okio:${property("okio_version")}") } } val commonTest by getting { dependencies { - implementation("com.squareup.okio:okio:3.1.0") + implementation("com.squareup.okio:okio:${property("okio_version")}") } } } 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 index 0f15377aa..a2d4cfedd 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -9,18 +9,18 @@ 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.decodeToSequence +import kotlinx.serialization.json.internal.decodeToSequenceByReader import kotlinx.serialization.json.okio.internal.OkioSerialReader import okio.BufferedSink import okio.BufferedSource /** -* Serializes the [value] with [serializer] into a [target] using JSON format and UTF-8 encoding. -* -* @throws [SerializationException] if the given value cannot be serialized to JSON. -*/ + * Serializes the [value] with [serializer] into a [target] using JSON format and UTF-8 encoding. + * + * @throws [SerializationException] or [okio.IOException] if the given value cannot be serialized to JSON. + */ @ExperimentalSerializationApi -public fun Json.encodeToOkio( +public fun Json.encodeToBufferedSink( serializer: SerializationStrategy, value: T, target: BufferedSink @@ -36,15 +36,13 @@ public fun Json.encodeToOkio( /** * Serializes given [value] to a [target] using UTF-8 encoding and serializer retrieved from the reified type parameter. * - * @throws [SerializationException] if the given value cannot be serialized to JSON. + * @throws [SerializationException] or [okio.IOException] if the given value cannot be serialized to JSON. */ @ExperimentalSerializationApi -public inline fun Json.encodeToOkio( +public inline fun Json.encodeToBufferedSink( value: T, target: BufferedSink -): Unit = - encodeToOkio(serializersModule.serializer(), value, target) - +): Unit = encodeToBufferedSink(serializersModule.serializer(), value, target) /** @@ -53,10 +51,10 @@ public inline fun Json.encodeToOkio( * 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 [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public fun Json.decodeFromOkio( +public fun Json.decodeFromBufferedSource( deserializer: DeserializationStrategy, source: BufferedSource ): T { @@ -70,16 +68,16 @@ public fun Json.decodeFromOkio( * 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 [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public inline fun Json.decodeFromOkio(source: BufferedSource): T = - decodeFromOkio(serializersModule.serializer(), source) +public inline fun Json.decodeFromBufferedSource(source: BufferedSource): T = + decodeFromBufferedSource(serializersModule.serializer(), source) /** * Transforms the given [source] into lazily deserialized sequence of elements of type [T] using UTF-8 encoding and [deserializer]. - * Unlike [decodeFromOkio], [source] is allowed to have more than one element, separated as [format] declares. + * Unlike [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. @@ -89,20 +87,20 @@ public inline fun Json.decodeFromOkio(source: BufferedSource): T = * 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 [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public fun Json.decodeOkioToSequence( +public fun Json.decodeBufferedSourceToSequence( source: BufferedSource, deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence { - return decodeToSequence(OkioSerialReader(source), deserializer, format) + return decodeToSequenceByReader(OkioSerialReader(source), 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 [decodeFromOkio], [source] is allowed to have more than one element, separated as [format] declares. + * Unlike [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. * * Elements must all be of type [T]. * Elements are parsed lazily when resulting [Sequence] is evaluated. @@ -112,10 +110,10 @@ public fun Json.decodeOkioToSequence( * 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 [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public inline fun Json.decodeOkioToSequence( +public inline fun Json.decodeBufferedSourceToSequence( source: BufferedSource, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT -): Sequence = decodeOkioToSequence(source, serializersModule.serializer(), format) +): Sequence = decodeBufferedSourceToSequence(source, serializersModule.serializer(), format) diff --git a/formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt b/formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt deleted file mode 100644 index dbcd46990..000000000 --- a/formats/json-okio/commonTest/src/kotlinx/serialization/json/okio/TestTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import okio.* -import kotlin.test.Test -import kotlin.test.assertEquals - - -class TestTest { - private val strLen = 1024 * 2 + 42 - - @Serializable - data class StringHolder(val data: String) - - @Test - fun testParsesStringsLongerThanBuffer() { - val str = "a".repeat(strLen) - val input = """{"data":"$str"}""" - assertEquals(input, Json.encodeViaOkio(StringHolder.serializer(), StringHolder(str))) - } - @Test - fun test2() { - val str = "a".repeat(strLen) - - val buffer = Buffer() - - Json.encodeToOkio(StringHolder.serializer(), StringHolder(str), buffer) - - val result = Json.decodeFromOkio(StringHolder.serializer(), buffer) - - assertEquals(StringHolder(str), result) - } - @Test - fun test4() { - val str = "a".repeat(strLen) - - val buffer = Buffer() - - Json.encodeToOkio(StringHolder(str), buffer) - Json.decodeOkioToSequence(buffer, StringHolder.serializer()) - } -} - -fun Json.encodeViaOkio(serializer: KSerializer, value: T): String { - val limited = Buffer() - - encodeToOkio(serializer, value, limited) - - return limited.readUtf8() - -} diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts index 3b722f898..f9e2252ec 100644 --- a/formats/json-tests/build.gradle.kts +++ b/formats/json-tests/build.gradle.kts @@ -7,7 +7,7 @@ plugins { kotlin("multiplatform") kotlin("plugin.serialization") } -// + apply(from = rootProject.file("gradle/native-targets.gradle")) apply(from = rootProject.file("gradle/configure-source-sets.gradle")) @@ -17,13 +17,24 @@ tasks.withType { } } +// disable kover tasks because there are no non-test classes in the project +tasks.koverHtmlReport { + enabled = false +} +tasks.koverXmlReport { + enabled = false +} +tasks.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:3.1.0") + implementation("com.squareup.okio:okio:${property("okio_version")}") } } diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt index 6e23b896f..59726d41f 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt @@ -6,8 +6,8 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.json.internal.* -import kotlinx.serialization.json.okio.decodeFromOkio -import kotlinx.serialization.json.okio.encodeToOkio +import kotlinx.serialization.json.okio.decodeFromBufferedSource +import kotlinx.serialization.json.okio.encodeToBufferedSink import kotlinx.serialization.modules.EmptySerializersModule import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.test.* @@ -53,7 +53,7 @@ abstract class JsonTestBase { } JsonTestingMode.OKIO_STREAMS -> { val buffer = Buffer() - encodeToOkio(serializer, value, buffer) + encodeToBufferedSink(serializer, value, buffer) buffer.readUtf8() } } @@ -76,16 +76,13 @@ 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) - decodeFromOkio(deserializer, buffer) + decodeFromBufferedSource(deserializer, buffer) } } diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt index 093763a2f..c31e4919c 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestingFramework.kt @@ -74,7 +74,7 @@ inline fun assertFailsWithSerialMessage( assertEquals( exceptionName, exception::class.simpleName, - "Expected message '${exception.message}' to contain substring '$message'" + "Expected exception type '$exceptionName' but actual is '${exception::class.simpleName}'" ) assertTrue( exception.message!!.contains(message), diff --git a/formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt b/formats/json-tests/jsTest/src/kotlinx/serialization/json/DynamicToLongTest.kt index 9c5011a81..2daf0bb2a 100644 --- a/formats/json-tests/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-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt index d2e86b2d3..0de89d9c5 100644 --- a/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt +++ b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt @@ -72,11 +72,16 @@ class JsonJvmStreamsTest { fun testRandomEscapeSequences() { repeat(1000) { val s = generateRandomUnicodeString(strLen) + try { val serializer = String.serializer() val b = ByteArrayOutputStream() Json.encodeToStream(serializer, s, b) val restored = Json.decodeFromStream(serializer, ByteArrayInputStream(b.toByteArray())) assertEquals(s, restored) + } catch (e: Throwable) { + // Not assertion error to preserve cause + throw IllegalStateException("Unexpectedly failed test, cause string: $s", e) + } } } diff --git a/formats/json/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index fd1c624ce..76b2ce1d7 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -366,28 +366,14 @@ 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 abstract class kotlinx/serialization/json/internal/AbstractJsonLexer { - protected field currentPosition I - public fun ()V - protected fun appendRange (II)V - protected final fun consumeString (Ljava/lang/CharSequence;II)Ljava/lang/String; - public final fun expectEof ()V - protected final fun getEscapedString ()Ljava/lang/StringBuilder; - protected abstract fun getSource ()Ljava/lang/CharSequence; - protected final fun isValidValueStart (C)Z - protected final fun setEscapedString (Ljava/lang/StringBuilder;)V - public fun toString ()Ljava/lang/String; - protected final fun unexpectedToken (C)V -} - public final class kotlinx/serialization/json/internal/JsonLexerKt { public static final field BATCH_SIZE I } 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 decodeToSequence (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/SerialReader;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; - public static synthetic fun decodeToSequence$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 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 } @@ -403,39 +389,8 @@ public abstract interface class kotlinx/serialization/json/internal/SerialReader public abstract fun read ([CII)I } -public class kotlinx/serialization/json/internal/StreamingJsonDecoder : kotlinx/serialization/encoding/AbstractDecoder, kotlinx/serialization/json/JsonDecoder { - public fun (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/json/internal/WriteMode;Lkotlinx/serialization/json/internal/AbstractJsonLexer;Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlinx/serialization/json/internal/StreamingJsonDecoder$DiscriminatorHolder;)V - public fun beginStructure (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeDecoder; - public fun decodeBoolean ()Z - public fun decodeByte ()B - public fun decodeChar ()C - public fun decodeDouble ()D - public fun decodeElementIndex (Lkotlinx/serialization/descriptors/SerialDescriptor;)I - public fun decodeEnum (Lkotlinx/serialization/descriptors/SerialDescriptor;)I - public fun decodeFloat ()F - public fun decodeInline (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/Decoder; - public fun decodeInt ()I - public fun decodeJsonElement ()Lkotlinx/serialization/json/JsonElement; - public fun decodeLong ()J - public fun decodeNotNullMark ()Z - public fun decodeNull ()Ljava/lang/Void; - public fun decodeSerializableElement (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/DeserializationStrategy;Ljava/lang/Object;)Ljava/lang/Object; - public fun decodeSerializableValue (Lkotlinx/serialization/DeserializationStrategy;)Ljava/lang/Object; - public fun decodeShort ()S - public fun decodeString ()Ljava/lang/String; - public fun endStructure (Lkotlinx/serialization/descriptors/SerialDescriptor;)V - public final fun getJson ()Lkotlinx/serialization/json/Json; - public fun getSerializersModule ()Lkotlinx/serialization/modules/SerializersModule; -} - -public final class kotlinx/serialization/json/internal/StreamingJsonDecoder$DiscriminatorHolder { - public field discriminatorToSkip Ljava/lang/String; - public fun (Ljava/lang/String;)V -} - -public final class kotlinx/serialization/json/internal/StringJsonLexer : kotlinx/serialization/json/internal/AbstractJsonLexer { - public fun (Ljava/lang/String;)V - public synthetic fun getSource ()Ljava/lang/CharSequence; +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/StringOpsKt { @@ -451,12 +406,3 @@ 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; } -public final class kotlinx/serialization/json/internal/WriteMode : java/lang/Enum { - public static final field LIST Lkotlinx/serialization/json/internal/WriteMode; - public static final field MAP Lkotlinx/serialization/json/internal/WriteMode; - public static final field OBJ Lkotlinx/serialization/json/internal/WriteMode; - public static final field POLY_OBJ Lkotlinx/serialization/json/internal/WriteMode; - public static fun valueOf (Ljava/lang/String;)Lkotlinx/serialization/json/internal/WriteMode; - public static fun values ()[Lkotlinx/serialization/json/internal/WriteMode; -} - diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt b/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt index c9eabab3a..abb9b4bc9 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt @@ -125,7 +125,7 @@ public sealed class Json( } /** - * Description of [decodeToSequence]'s JSON input shape. + * 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. diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt index d3616bc76..757032495 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonStreams.kt @@ -47,7 +47,7 @@ public fun Json.decodeByReader( @InternalSerializationApi @ExperimentalSerializationApi -public fun Json.decodeToSequence( +public fun Json.decodeToSequenceByReader( reader: SerialReader, deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT @@ -59,7 +59,7 @@ public fun Json.decodeToSequence( @InternalSerializationApi @ExperimentalSerializationApi -public inline fun Json.decodeToSequence( +public inline fun Json.decodeToSequenceByReader( reader: SerialReader, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT -): Sequence = decodeToSequence(reader, serializersModule.serializer(), format) +): Sequence = decodeToSequenceByReader(reader, serializersModule.serializer(), format) 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 62c7c198e..925cb303b 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt @@ -18,8 +18,7 @@ import kotlin.jvm.* * [JsonDecoder] which reads given JSON from [AbstractJsonLexer] field by field. */ @OptIn(ExperimentalSerializationApi::class) -@InternalSerializationApi -public open class StreamingJsonDecoder( +internal open class StreamingJsonDecoder( final override val json: Json, private val mode: WriteMode, @JvmField internal val lexer: AbstractJsonLexer, @@ -354,6 +353,18 @@ public 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/StringOps.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt index 45c520df1..f543e8fb5 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt @@ -4,6 +4,7 @@ package kotlinx.serialization.json.internal +import kotlinx.serialization.InternalSerializationApi import kotlin.native.concurrent.* private fun toHexChar(i: Int) : Char { @@ -13,6 +14,7 @@ private fun toHexChar(i: Int) : Char { } @SharedImmutable +@InternalSerializationApi public val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { for (c in 0..0x1f) { val c1 = toHexChar(c shr 12) diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt index 1341499cd..382d8bce4 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/WriteMode.kt @@ -11,8 +11,7 @@ import kotlinx.serialization.json.* import kotlinx.serialization.modules.* import kotlin.jvm.* -@InternalSerializationApi -public enum class WriteMode(@JvmField internal val begin: Char, @JvmField internal val end: Char) { +internal enum class WriteMode(@JvmField val begin: Char, @JvmField val end: Char) { OBJ(BEGIN_OBJ, END_OBJ), LIST(BEGIN_LIST, END_LIST), MAP(BEGIN_OBJ, END_OBJ), diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt index c2d8fc5f6..977347a55 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/AbstractJsonLexer.kt @@ -4,7 +4,7 @@ package kotlinx.serialization.json.internal -import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.json.internal.* import kotlinx.serialization.json.internal.CharMappings.CHAR_TO_TOKEN import kotlinx.serialization.json.internal.CharMappings.ESCAPE_2_CHAR import kotlin.js.* @@ -130,8 +130,7 @@ internal fun escapeToChar(c: Int): Char = if (c < ESC2C_MAX) ESCAPE_2_CHAR[c] el * of them for the performance reasons (devirtualization of [CharSequence] and avoid * of additional spills). */ -@InternalSerializationApi -public abstract class AbstractJsonLexer { +internal abstract class AbstractJsonLexer { protected abstract val source: CharSequence @@ -139,20 +138,20 @@ public abstract class AbstractJsonLexer { protected var currentPosition: Int = 0 // position in source @JvmField - internal val path = JsonPath() + val path = JsonPath() - internal open fun ensureHaveChars() {} + open fun ensureHaveChars() {} - internal fun isNotEof(): Boolean = peekNextToken() != TC_EOF + fun isNotEof(): Boolean = peekNextToken() != TC_EOF // Used as bound check in loops - internal abstract fun prefetchOrEof(position: Int): Int + abstract fun prefetchOrEof(position: Int): Int - internal abstract fun tryConsumeComma(): Boolean + abstract fun tryConsumeComma(): Boolean - internal abstract fun canConsumeValue(): Boolean + abstract fun canConsumeValue(): Boolean - internal abstract fun consumeNextToken(): Byte + abstract fun consumeNextToken(): Byte protected fun isValidValueStart(c: Char): Boolean { return when (c) { @@ -161,7 +160,7 @@ public abstract class AbstractJsonLexer { } } - public fun expectEof() { + fun expectEof() { val nextToken = consumeNextToken() if (nextToken != TC_EOF) fail("Expected EOF after parsing, but had ${source[currentPosition - 1]} instead") @@ -172,10 +171,10 @@ public abstract class AbstractJsonLexer { * If the value was picked, 'consumeString' will take it without scanning the source. */ private var peekedString: String? = null - protected var escapedString: StringBuilder = StringBuilder() + protected var escapedString = StringBuilder() // TODO consider replacing usages of this method in JsonParser with char overload - internal fun consumeNextToken(expected: Byte): Byte { + fun consumeNextToken(expected: Byte): Byte { val token = consumeNextToken() if (token != expected) { fail(expected) @@ -183,7 +182,7 @@ public abstract class AbstractJsonLexer { return token } - internal open fun consumeNextToken(expected: Char) { + open fun consumeNextToken(expected: Char) { ensureHaveChars() val source = source var cpos = currentPosition @@ -225,7 +224,7 @@ public abstract class AbstractJsonLexer { fail("Expected $expected, but had '$s' instead", currentPosition - 1) } - internal fun peekNextToken(): Byte { + fun peekNextToken(): Byte { val source = source var cpos = currentPosition while (true) { @@ -248,7 +247,7 @@ public abstract class AbstractJsonLexer { * Returns `true` if the next 4 chars in input are not `null`, * `false` otherwise and consumes it. */ - internal fun tryConsumeNotNull(): Boolean { + fun tryConsumeNotNull(): Boolean { var current = skipWhitespaces() current = prefetchOrEof(current) // Cannot consume null due to EOF, maybe something else @@ -266,7 +265,7 @@ public abstract class AbstractJsonLexer { return false } - internal open fun skipWhitespaces(): Int { + open fun skipWhitespaces(): Int { var current = currentPosition // Skip whitespaces while (true) { @@ -284,9 +283,9 @@ public abstract class AbstractJsonLexer { return current } - internal abstract fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? + abstract fun consumeLeadingMatchingValue(keyToMatch: String, isLenient: Boolean): String? - internal fun peekString(isLenient: Boolean): String? { + fun peekString(isLenient: Boolean): String? { val token = peekNextToken() val string = if (isLenient) { if (token != TC_STRING && token != TC_OTHER) return null @@ -299,16 +298,16 @@ public abstract class AbstractJsonLexer { return string } - internal open fun indexOf(char: Char, startPos: Int) = source.indexOf(char, startPos) - internal open fun substring(startPos: Int, endPos: Int) = source.substring(startPos, endPos) + open fun indexOf(char: Char, startPos: Int) = source.indexOf(char, startPos) + open fun substring(startPos: Int, endPos: Int) = source.substring(startPos, endPos) /* * This method is a copy of consumeString, but used for key of json objects, so there * is no need to lookup peeked string. */ - internal abstract fun consumeKeyString(): String + abstract fun consumeKeyString(): String - internal fun consumeString(): String { + fun consumeString(): String { if (peekedString != null) { return takePeeked() } @@ -368,7 +367,7 @@ public abstract class AbstractJsonLexer { return peekedString!!.also { peekedString = null } } - internal fun consumeStringLenientNotNull(): String { + fun consumeStringLenientNotNull(): String { val result = consumeStringLenient() /* * Check if lenient value is 'null' _without_ quotation marks and fail for non-nullable read if so. @@ -385,7 +384,7 @@ public abstract class AbstractJsonLexer { } // Allows consuming unquoted string - internal fun consumeStringLenient(): String { + fun consumeStringLenient(): String { if (peekedString != null) { return takePeeked() } @@ -474,7 +473,7 @@ public abstract class AbstractJsonLexer { } } - internal fun skipElement(allowLenientStrings: Boolean) { + fun skipElement(allowLenientStrings: Boolean) { val tokenStack = mutableListOf() var lastToken = peekNextToken() if (lastToken != TC_BEGIN_LIST && lastToken != TC_BEGIN_OBJ) { @@ -518,7 +517,7 @@ public abstract class AbstractJsonLexer { return "JsonReader(source='$source', currentPosition=$currentPosition)" } - internal fun failOnUnknownKey(key: String) { + fun failOnUnknownKey(key: String) { // At this moment we already have both key and semicolon (and whitespaces! consumed), // but still would like an error to point to the beginning of the key, so we are backtracking it val processed = substring(0, currentPosition) @@ -526,12 +525,12 @@ public abstract class AbstractJsonLexer { fail("Encountered an unknown key '$key'", lastIndexOf, ignoreUnknownKeysHint) } - internal fun fail(message: String, position: Int = currentPosition, hint: String = ""): Nothing { + fun fail(message: String, position: Int = currentPosition, hint: String = ""): Nothing { val hintMessage = if (hint.isEmpty()) "" else "\n$hint" throw JsonDecodingException(position, message + " at path: " + path.getPath() + hintMessage, source) } - internal fun consumeNumericLiteral(): Long { + fun consumeNumericLiteral(): Long { /* * This is an optimized (~40% for numbers) version of consumeString().toLong() * that doesn't allocate and also doesn't support any radix but 10 @@ -585,11 +584,11 @@ public abstract class AbstractJsonLexer { } - internal fun consumeBoolean(): Boolean { + fun consumeBoolean(): Boolean { return consumeBoolean(skipWhitespaces()) } - internal fun consumeBooleanLenient(): Boolean { + fun consumeBooleanLenient(): Boolean { var current = skipWhitespaces() if (current == source.length) fail("EOF") val hasQuotation = if (source[current] == STRING) { diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt index 40ac6f61e..9ccfbcc1d 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/StringJsonLexer.kt @@ -4,10 +4,7 @@ package kotlinx.serialization.json.internal -import kotlinx.serialization.InternalSerializationApi - -@InternalSerializationApi -public class StringJsonLexer(override val source: String) : AbstractJsonLexer() { +internal class StringJsonLexer(override val source: String) : AbstractJsonLexer() { override fun prefetchOrEof(position: Int): Int = if (position < source.length) position else -1 diff --git a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt index 1bc825a50..a6658c7cb 100644 --- a/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt +++ b/formats/json/jsMain/src/kotlinx/serialization/json/internal/DynamicDecoders.kt @@ -15,8 +15,7 @@ import kotlin.math.* /** * [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER] */ -@InternalSerializationApi -public const val MAX_SAFE_INTEGER: Double = 9007199254740991.toDouble() // 2^53 - 1 +internal const val MAX_SAFE_INTEGER: Double = 9007199254740991.toDouble() // 2^53 - 1 @JsName("decodeDynamic") internal fun Json.decodeDynamic(deserializer: DeserializationStrategy, dynamic: dynamic): T { diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt index 938b4e677..04d8149b8 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/JvmStreams.kt @@ -94,7 +94,7 @@ public fun Json.decodeToSequence( deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence { - return decodeToSequence(JavaStreamSerialReader(stream), deserializer, format) + return decodeToSequenceByReader(JavaStreamSerialReader(stream), deserializer, format) } /** diff --git a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt index 4bf0c4f32..17eac0a2a 100644 --- a/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt +++ b/formats/json/jvmMain/src/kotlinx/serialization/json/internal/JvmJsonStreams.kt @@ -6,8 +6,8 @@ import java.nio.charset.Charset internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWriter { private val buffer = ByteArrayPool.take() - private var array = CharArrayPool.take() - private var index: Int = 0 + private var charArray = CharArrayPool.take() + private var indexInBuffer: Int = 0 override fun writeLong(value: Long) { write(value.toString()) @@ -20,13 +20,13 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr override fun write(text: String) { val length = text.length ensureTotalCapacity(0, length) - text.toCharArray(array, 0, 0, length) - writeUtf8(array, 0, length) + text.toCharArray(charArray, 0, 0, length) + writeUtf8(charArray, length) } override fun writeQuoted(text: String) { ensureTotalCapacity(0, text.length + 2) - val arr = array + val arr = charArray arr[0] = '"' val length = text.length text.toCharArray(arr, 1, 0, length) @@ -43,7 +43,7 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr arr[length + 1] = '"' - writeUtf8(arr, 0, length + 2) + writeUtf8(arr, length + 2) flush() } @@ -66,47 +66,47 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr */ when (val marker = ESCAPE_MARKERS[ch]) { 0.toByte() -> { - array[sz++] = ch.toChar() + charArray[sz++] = ch.toChar() } 1.toByte() -> { val escapedString = ESCAPE_STRINGS[ch]!! sz = ensureTotalCapacity(sz, escapedString.length) - escapedString.toCharArray(array, sz, 0, escapedString.length) + escapedString.toCharArray(charArray, sz, 0, escapedString.length) sz += escapedString.length } else -> { - array[sz] = '\\' - array[sz + 1] = marker.toInt().toChar() + charArray[sz] = '\\' + charArray[sz + 1] = marker.toInt().toChar() sz += 2 } } } else { - array[sz++] = ch.toChar() + charArray[sz++] = ch.toChar() } } ensureTotalCapacity(sz, 1) - array[sz++] = '"' - writeUtf8(array, 0, sz) + charArray[sz++] = '"' + writeUtf8(charArray, sz) flush() } private fun ensureTotalCapacity(oldSize: Int, additional: Int): Int { val newSize = oldSize + additional - if (array.size <= newSize) { - array = array.copyOf(newSize.coerceAtLeast(oldSize * 2)) + if (charArray.size <= newSize) { + charArray = charArray.copyOf(newSize.coerceAtLeast(oldSize * 2)) } return oldSize } override fun release() { flush() - CharArrayPool.release(array) + CharArrayPool.release(charArray) ByteArrayPool.release(buffer) } private fun flush() { - stream.write(buffer, 0, index) - index = 0 + stream.write(buffer, 0, indexInBuffer) + indexInBuffer = 0 } @@ -121,22 +121,24 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr @Suppress("NOTHING_TO_INLINE") // ! you should never ask for more than the buffer size private inline fun write(byte: Int) { - buffer[index++] = byte.toByte() + buffer[indexInBuffer++] = byte.toByte() } @Suppress("NOTHING_TO_INLINE") private inline fun rest(): Int { - return buffer.size - index + return buffer.size - indexInBuffer } - private fun writeUtf8(string: CharArray, beginIndex: Int, endIndex: Int) { - require(beginIndex >= 0) { "beginIndex < 0: $beginIndex" } - require(endIndex >= beginIndex) { "endIndex < beginIndex: $endIndex < $beginIndex" } - require(endIndex <= string.size) { "endIndex > string.length: $endIndex > ${string.size}" } + /* + 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 = beginIndex - while (i < endIndex) { + var i = 0 + while (i < count) { var c = string[i].code when { @@ -145,7 +147,7 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr ensure(1) write(c) // 0xxxxxxx i++ - val runLimit = minOf(endIndex, i + rest()) + 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(). @@ -160,21 +162,17 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr c < 0x800 -> { // Emit a 11-bit character with 2 bytes. ensure(2) - /* ktlint-disable no-multi-spaces */ write(c shr 6 or 0xc0) // 110xxxxx write(c and 0x3f or 0x80) // 10xxxxxx - /* ktlint-enable no-multi-spaces */ i++ } c < 0xd800 || c > 0xdfff -> { // Emit a 16-bit character with 3 bytes. ensure(3) - /* ktlint-disable no-multi-spaces */ write(c shr 12 or 0xe0) // 1110xxxx write(c shr 6 and 0x3f or 0x80) // 10xxxxxx write(c and 0x3f or 0x80) // 10xxxxxx - /* ktlint-enable no-multi-spaces */ i++ } @@ -182,7 +180,7 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr // 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 < endIndex) string[i + 1].code else 0) + val low = (if (i + 1 < count) string[i + 1].code else 0) if (c > 0xdbff || low !in 0xdc00..0xdfff) { ensure(1) write('?'.code) @@ -195,12 +193,10 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr // Emit a 21-bit character with 4 bytes. ensure(4) - /* ktlint-disable no-multi-spaces */ 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 - /* ktlint-enable no-multi-spaces */ i += 2 } } @@ -208,6 +204,9 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr } } + /* + Sources taken from okio library with minor changes, see https://github.com/square/okio + */ private fun writeUtf8CodePoint(codePoint: Int) { when { codePoint < 0x80 -> { @@ -218,10 +217,8 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr codePoint < 0x800 -> { // Emit a 11-bit code point with 2 bytes. ensure(2) - /* ktlint-disable no-multi-spaces */ write(codePoint shr 6 or 0xc0) // 110xxxxx write(codePoint and 0x3f or 0x80) // 10xxxxxx - /* ktlint-enable no-multi-spaces */ } codePoint in 0xd800..0xdfff -> { // Emit a replacement character for a partial surrogate. @@ -231,24 +228,20 @@ internal class JsonToJavaStreamWriter(private val stream: OutputStream) : JsonWr codePoint < 0x10000 -> { // Emit a 16-bit code point with 3 bytes. ensure(3) - /* ktlint-disable no-multi-spaces */ write(codePoint shr 12 or 0xe0) // 1110xxxx write(codePoint shr 6 and 0x3f or 0x80) // 10xxxxxx write(codePoint and 0x3f or 0x80) // 10xxxxxx - /* ktlint-enable no-multi-spaces */ } codePoint <= 0x10ffff -> { // Emit a 21-bit code point with 4 bytes. ensure(4) - /* ktlint-disable no-multi-spaces */ 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 - /* ktlint-enable no-multi-spaces */ } else -> { - throw IllegalArgumentException("Unexpected code point: $codePoint") + throw JsonEncodingException("Unexpected code point: $codePoint") } } } 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 From 7eb0479c4bb0af700254907261e5f1f18843eb04 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 12:27:59 +0300 Subject: [PATCH 21/27] changed buffered to pure Sink/Source --- .../api/kotlinx-serialization-json-okio.api | 8 +-- .../serialization/json/okio/OkioStreams.kt | 56 ++++++++++++------- .../serialization/json/JsonTestBase.kt | 8 +-- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/formats/json-okio/api/kotlinx-serialization-json-okio.api b/formats/json-okio/api/kotlinx-serialization-json-okio.api index 75effa13f..4b3f0a2c3 100644 --- a/formats/json-okio/api/kotlinx-serialization-json-okio.api +++ b/formats/json-okio/api/kotlinx-serialization-json-okio.api @@ -1,7 +1,7 @@ public final class kotlinx/serialization/json/okio/OkioStreamsKt { - public static final fun decodeBufferedSourceToSequence (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;)Lkotlin/sequences/Sequence; - public static synthetic fun decodeBufferedSourceToSequence$default (Lkotlinx/serialization/json/Json;Lokio/BufferedSource;Lkotlinx/serialization/DeserializationStrategy;Lkotlinx/serialization/json/DecodeSequenceMode;ILjava/lang/Object;)Lkotlin/sequences/Sequence; - public static final fun decodeFromBufferedSource (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/DeserializationStrategy;Lokio/BufferedSource;)Ljava/lang/Object; - public static final fun encodeToBufferedSink (Lkotlinx/serialization/json/Json;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lokio/BufferedSink;)V + 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/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt index a2d4cfedd..7e038f5ed 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -11,21 +11,23 @@ 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.BufferedSink -import okio.BufferedSource +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] or [okio.IOException] if the given value cannot be serialized to JSON. */ @ExperimentalSerializationApi -public fun Json.encodeToBufferedSink( +public fun Json.encodeToSink( serializer: SerializationStrategy, value: T, - target: BufferedSink + target: Sink ) { - val writer = JsonToOkioStreamWriter(target) + val buffered = if (target is BufferedSink) target else target.buffer() + val writer = JsonToOkioStreamWriter(buffered) try { encodeByWriter(writer, serializer, value) } finally { @@ -36,48 +38,57 @@ public fun Json.encodeToBufferedSink( /** * 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] or [okio.IOException] if the given value cannot be serialized to JSON. */ @ExperimentalSerializationApi -public inline fun Json.encodeToBufferedSink( +public inline fun Json.encodeToSink( value: T, - target: BufferedSink -): Unit = encodeToBufferedSink(serializersModule.serializer(), value, target) + 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public fun Json.decodeFromBufferedSource( +public fun Json.decodeFromSource( deserializer: DeserializationStrategy, - source: BufferedSource + source: Source ): T { - return decodeByReader(deserializer, OkioSerialReader(source)) + 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public inline fun Json.decodeFromBufferedSource(source: BufferedSource): T = - decodeFromBufferedSource(serializersModule.serializer(), source) +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 [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. + * 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. @@ -90,17 +101,20 @@ public inline fun Json.decodeFromBufferedSource(source: BufferedSour * @throws [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public fun Json.decodeBufferedSourceToSequence( - source: BufferedSource, +public fun Json.decodeSourceToSequence( + source: Source, deserializer: DeserializationStrategy, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT ): Sequence { - return decodeToSequenceByReader(OkioSerialReader(source), deserializer, format) + 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 [decodeFromBufferedSource], [source] is allowed to have more than one element, separated as [format] declares. + * 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. @@ -113,7 +127,7 @@ public fun Json.decodeBufferedSourceToSequence( * @throws [SerializationException] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. */ @ExperimentalSerializationApi -public inline fun Json.decodeBufferedSourceToSequence( - source: BufferedSource, +public inline fun Json.decodeSourceToSequence( + source: Source, format: DecodeSequenceMode = DecodeSequenceMode.AUTO_DETECT -): Sequence = decodeBufferedSourceToSequence(source, serializersModule.serializer(), format) +): Sequence = decodeSourceToSequence(source, serializersModule.serializer(), format) diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt index 59726d41f..33f23b819 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTestBase.kt @@ -6,8 +6,8 @@ package kotlinx.serialization.json import kotlinx.serialization.* import kotlinx.serialization.json.internal.* -import kotlinx.serialization.json.okio.decodeFromBufferedSource -import kotlinx.serialization.json.okio.encodeToBufferedSink +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.* @@ -53,7 +53,7 @@ abstract class JsonTestBase { } JsonTestingMode.OKIO_STREAMS -> { val buffer = Buffer() - encodeToBufferedSink(serializer, value, buffer) + encodeToSink(serializer, value, buffer) buffer.readUtf8() } } @@ -82,7 +82,7 @@ abstract class JsonTestBase { JsonTestingMode.OKIO_STREAMS -> { val buffer = Buffer() buffer.writeUtf8(source) - decodeFromBufferedSource(deserializer, buffer) + decodeFromSource(deserializer, buffer) } } From aa268b947f451b64cdedf546388ec70ec427f67b Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 12:57:39 +0300 Subject: [PATCH 22/27] replaced JsonLiteral to JsonPrimitive in tests --- .../src/kotlinx/serialization/json/JsonParserTest.kt | 4 ++-- .../json/serializers/JsonArraySerializerTest.kt | 2 +- formats/json/api/kotlinx-serialization-json.api | 8 -------- .../src/kotlinx/serialization/json/JsonElement.kt | 3 +-- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonParserTest.kt index 8062f4dda..7f9044f9d 100644 --- a/formats/json-tests/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,7 +25,7 @@ class JsonParserTest : JsonTestBase() { fun testEmptyKey() { val tree = parse("""{"":"","":""}""") assertTrue("" in tree) - assertEquals("", (tree.getValue("") as JsonLiteral).content) + assertEquals("", (tree.getValue("") as JsonPrimitive).content) } @Test diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt index 266e9e975..c571ec9ed 100644 --- a/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/serializers/JsonArraySerializerTest.kt @@ -41,7 +41,7 @@ class JsonArraySerializerTest : JsonTestBase() { val json = """[1, "2", 3, "4"]""" 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) } } diff --git a/formats/json/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index 76b2ce1d7..407210367 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -232,14 +232,6 @@ public final class kotlinx/serialization/json/JsonKt { public static synthetic fun Json$default (Lkotlinx/serialization/json/Json;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/serialization/json/Json; } -public final class kotlinx/serialization/json/JsonLiteral : kotlinx/serialization/json/JsonPrimitive { - public fun equals (Ljava/lang/Object;)Z - public fun getContent ()Ljava/lang/String; - public fun hashCode ()I - public fun isString ()Z - public fun toString ()Ljava/lang/String; -} - public abstract interface annotation class kotlinx/serialization/json/JsonNames : java/lang/annotation/Annotation { public abstract fun names ()[Ljava/lang/String; } diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt b/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt index 8cb4b6013..07b5973a3 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/JsonElement.kt @@ -77,8 +77,7 @@ public fun JsonPrimitive(value: String?): JsonPrimitive { public fun JsonPrimitive(value: Nothing?): JsonNull = JsonNull // JsonLiteral is deprecated for public use and no longer available. Please use JsonPrimitive instead -@InternalSerializationApi -public class JsonLiteral internal constructor( +internal class JsonLiteral internal constructor( body: Any, public override val isString: Boolean ) : JsonPrimitive() { From 5afaf42da2a0c7a6f592f32da33a8507ba2cf06b Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 13:42:43 +0300 Subject: [PATCH 23/27] fixes --- formats/json-tests/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/formats/json-tests/build.gradle.kts b/formats/json-tests/build.gradle.kts index f9e2252ec..5e18b6078 100644 --- a/formats/json-tests/build.gradle.kts +++ b/formats/json-tests/build.gradle.kts @@ -18,13 +18,13 @@ tasks.withType { } // disable kover tasks because there are no non-test classes in the project -tasks.koverHtmlReport { +tasks.named("koverHtmlReport") { enabled = false } -tasks.koverXmlReport { +tasks.named("koverXmlReport") { enabled = false } -tasks.koverVerify { +tasks.named("koverVerify") { enabled = false } From f1f2f02a3a0193e595cf19090b1bd067bde189c1 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 17:23:22 +0300 Subject: [PATCH 24/27] review fixes --- .../serialization/json/okio/OkioStreams.kt | 18 ++++++++++++------ .../json/internal/StreamingJsonDecoder.kt | 2 +- .../serialization/json/internal/StringOps.kt | 9 +++++---- 3 files changed, 18 insertions(+), 11 deletions(-) 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 index 7e038f5ed..b666d839a 100644 --- a/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt +++ b/formats/json-okio/commonMain/src/kotlinx/serialization/json/okio/OkioStreams.kt @@ -18,7 +18,8 @@ import okio.* * * If [target] is not a [BufferedSink] then called [Sink.buffer] for it to create buffered wrapper. * - * @throws [SerializationException] or [okio.IOException] if the given value cannot be serialized to JSON. + * @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( @@ -40,7 +41,8 @@ public fun Json.encodeToSink( * * If [target] is not a [BufferedSink] then called [Sink.buffer] for it to create buffered wrapper. * - * @throws [SerializationException] or [okio.IOException] if the given value cannot be serialized to JSON. + * @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( @@ -57,7 +59,8 @@ public inline fun Json.encodeToSink( * 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. + * @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( @@ -77,7 +80,8 @@ public fun Json.decodeFromSource( * 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. + * @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 = @@ -98,7 +102,8 @@ public inline fun Json.decodeFromSource(source: Source): T = * 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. + * @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( @@ -124,7 +129,8 @@ public fun Json.decodeSourceToSequence( * 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] or [okio.IOException] if the given JSON input cannot be deserialized to the value of type [T]. + * @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( 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 925cb303b..3505a9c5f 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt @@ -28,7 +28,7 @@ internal open class StreamingJsonDecoder( // A mutable reference to the discriminator that have to be skipped when in optimistic phase // of polymorphic serialization, see `decodeSerializableValue` - public class DiscriminatorHolder(@JvmField public var discriminatorToSkip: String?) + internal class DiscriminatorHolder(@JvmField var discriminatorToSkip: String?) private fun DiscriminatorHolder?.trySkip(unknownKey: String): Boolean { if (this == null) return false 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 f543e8fb5..f5080ae58 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt @@ -2,9 +2,10 @@ * Copyright 2017-2019 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.internal -import kotlinx.serialization.InternalSerializationApi import kotlin.native.concurrent.* private fun toHexChar(i: Int) : Char { @@ -13,9 +14,9 @@ private fun toHexChar(i: Int) : Char { else (d - 10 + 'a'.code).toChar() } +@PublishedApi @SharedImmutable -@InternalSerializationApi -public val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { +internal val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { for (c in 0..0x1f) { val c1 = toHexChar(c shr 12) val c2 = toHexChar(c shr 8) @@ -33,7 +34,7 @@ public val ESCAPE_STRINGS: Array = arrayOfNulls(93).apply { } @SharedImmutable -public val ESCAPE_MARKERS: ByteArray = ByteArray(93).apply { +internal val ESCAPE_MARKERS: ByteArray = ByteArray(93).apply { for (c in 0..0x1f) { this[c] = 1.toByte() } From 844d14761185fcc6935c40c250cffe320158ff20 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 17:27:21 +0300 Subject: [PATCH 25/27] review fixes --- formats/json/api/kotlinx-serialization-json.api | 5 ----- 1 file changed, 5 deletions(-) diff --git a/formats/json/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index 407210367..c4c9f13e4 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -385,11 +385,6 @@ 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/StringOpsKt { - public static final fun getESCAPE_MARKERS ()[B - public static final fun getESCAPE_STRINGS ()[Ljava/lang/String; -} - 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; } From 95f9bbb14785421aafd2f32dec83f311beca6b64 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 19:28:15 +0300 Subject: [PATCH 26/27] review fixes --- .../json/okio/internal/OkioJsonStreams.kt | 2 ++ .../src/kotlinx/serialization/test/TestHelpers.kt | 5 ++++- .../serialization/features/JsonJvmStreamsTest.kt | 4 +++- formats/json/api/kotlinx-serialization-json.api | 4 ---- formats/json/build.gradle | 11 +++++++++++ .../kotlinx/serialization/json/internal/StringOps.kt | 2 -- .../serialization/json/internal/lexer/JsonLexer.kt | 8 ++++---- 7 files changed, 24 insertions(+), 12 deletions(-) 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 index b72b133d0..3537392b2 100644 --- 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 @@ -2,6 +2,8 @@ * 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 diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/test/TestHelpers.kt index d178c871c..04af40c6e 100644 --- a/formats/json-tests/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-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt b/formats/json-tests/jvmTest/src/kotlinx/serialization/features/JsonJvmStreamsTest.kt index 0de89d9c5..7019edae4 100644 --- a/formats/json-tests/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/api/kotlinx-serialization-json.api b/formats/json/api/kotlinx-serialization-json.api index c4c9f13e4..bdfbe731f 100644 --- a/formats/json/api/kotlinx-serialization-json.api +++ b/formats/json/api/kotlinx-serialization-json.api @@ -358,10 +358,6 @@ 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/JsonLexerKt { - public static final field BATCH_SIZE I -} - 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; diff --git a/formats/json/build.gradle b/formats/json/build.gradle index ec066ee94..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 { 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 f5080ae58..21bb8af9b 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/StringOps.kt @@ -2,8 +2,6 @@ * Copyright 2017-2019 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.internal import kotlin.native.concurrent.* diff --git a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt index ba5bf7518..e02364ee4 100644 --- a/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt +++ b/formats/json/commonMain/src/kotlinx/serialization/json/internal/lexer/JsonLexer.kt @@ -2,12 +2,12 @@ * 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 kotlinx.serialization.InternalSerializationApi +package kotlinx.serialization.json.internal -@InternalSerializationApi -public const val BATCH_SIZE: Int = 16 * 1024 +@PublishedApi +internal const val BATCH_SIZE: Int = 16 * 1024 private const val DEFAULT_THRESHOLD = 128 /** From 51a6faa9b641e4a6500372aa6200254edaad27d5 Mon Sep 17 00:00:00 2001 From: "Sergey.Shanshin" Date: Wed, 29 Jun 2022 20:19:45 +0300 Subject: [PATCH 27/27] Fixed benchmarks and added benchmark on okio --- benchmark/build.gradle | 21 +++++++++++------ .../json/JacksonComparisonBenchmark.kt | 23 +++++++++++++++++++ .../benchmarks/json/TwitterBenchmark.kt | 10 ++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) 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) }