diff options
Diffstat (limited to 'formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt')
-rw-r--r-- | formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt new file mode 100644 index 00000000..336f630e --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/json/JsonTreeAndMapperTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2017-2020 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.descriptors.* +import kotlinx.serialization.encoding.* +import kotlin.test.* + +class JsonTreeAndMapperTest { + private val decoderData = """{"id":0,"payload":{"from":42,"to":43,"msg":"Hello world"},"timestamp":1000}""" + private val decoderError = """{"id":1,"payload":{"error":"Connection timed out"},"timestamp":1001}""" + + @Serializable + data class Payload(val from: Long, val to: Long, val msg: String) + + sealed class Either { + data class Left(val errorMsg: String) : Either() + data class Right(val data: Payload) : Either() + } + + object EitherSerializer : KSerializer<Either> { + override val descriptor: SerialDescriptor = buildSerialDescriptor("Either", PolymorphicKind.SEALED) { + val leftDescriptor = buildClassSerialDescriptor("Either.Left") { + element<String>("errorMsg") + } + val rightDescriptor = buildClassSerialDescriptor("Either.Right") { + element("data", Payload.serializer().descriptor) + } + element("left", leftDescriptor) + element("right", rightDescriptor) + } + + override fun deserialize(decoder: Decoder): Either { + val input = decoder as? JsonDecoder ?: throw SerializationException("This class can be loaded only by Json") + val tree = input.decodeJsonElement() as? JsonObject + ?: throw SerializationException("Expected JsonObject") + if ("error" in tree) return Either.Left(tree.getValue("error").jsonPrimitive.content) + + return Either.Right(input.json.decodeFromJsonElement(Payload.serializer(), tree)) + } + + override fun serialize(encoder: Encoder, value: Either) { + val output = encoder as? JsonEncoder ?: throw SerializationException("This class can be saved only by Json") + val tree = when (value) { + is Either.Left -> JsonObject(mapOf("error" to JsonPrimitive(value.errorMsg))) + is Either.Right -> output.json.encodeToJsonElement(Payload.serializer(), value.data) + } + + output.encodeJsonElement(tree) + } + } + + @Serializable + data class Event( + val id: Int, + @Serializable(with = EitherSerializer::class) val payload: Either, + val timestamp: Long + ) + + @Test + fun testParseData() { + val ev = Json.decodeFromString(Event.serializer(), decoderData) + with(ev) { + assertEquals(0, id) + assertEquals(Either.Right(Payload(42, 43, "Hello world")), payload) + assertEquals(1000, timestamp) + } + } + + @Test + fun testParseError() { + val ev = Json.decodeFromString(Event.serializer(), decoderError) + with(ev) { + assertEquals(1, id) + assertEquals(Either.Left("Connection timed out"), payload) + assertEquals(1001, timestamp) + } + } + + @Test + fun testWriteData() { + val encoderData = Event(0, Either.Right(Payload(42, 43, "Hello world")), 1000) + val ev = Json.encodeToString(Event.serializer(), encoderData) + assertEquals(decoderData, ev) + } + + @Test + fun testWriteError() { + val encoderError = Event(1, Either.Left("Connection timed out"), 1001) + val ev = Json.encodeToString(Event.serializer(), encoderError) + assertEquals(decoderError, ev) + } +} |