• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.serialization.json
6 
7 import kotlinx.serialization.*
8 import kotlinx.serialization.descriptors.*
9 import kotlinx.serialization.encoding.*
10 import kotlin.test.*
11 
12 class JsonTreeAndMapperTest {
13     private val decoderData = """{"id":0,"payload":{"from":42,"to":43,"msg":"Hello world"},"timestamp":1000}"""
14     private val decoderError = """{"id":1,"payload":{"error":"Connection timed out"},"timestamp":1001}"""
15 
16     @Serializable
17     data class Payload(val from: Long, val to: Long, val msg: String)
18 
19     sealed class Either {
20         data class Left(val errorMsg: String) : Either()
21         data class Right(val data: Payload) : Either()
22     }
23 
24     object EitherSerializer : KSerializer<Either> {
<lambda>null25         override val descriptor: SerialDescriptor = buildSerialDescriptor("Either", PolymorphicKind.SEALED) {
26             val leftDescriptor = buildClassSerialDescriptor("Either.Left") {
27                 element<String>("errorMsg")
28             }
29             val rightDescriptor = buildClassSerialDescriptor("Either.Right") {
30                 element("data", Payload.serializer().descriptor)
31             }
32             element("left", leftDescriptor)
33             element("right", rightDescriptor)
34         }
35 
deserializenull36         override fun deserialize(decoder: Decoder): Either {
37             val input = decoder as? JsonDecoder ?: throw SerializationException("This class can be loaded only by Json")
38             val tree = input.decodeJsonElement() as? JsonObject
39                 ?: throw SerializationException("Expected JsonObject")
40             if ("error" in tree) return Either.Left(tree.getValue("error").jsonPrimitive.content)
41 
42             return Either.Right(input.json.decodeFromJsonElement(Payload.serializer(), tree))
43         }
44 
serializenull45         override fun serialize(encoder: Encoder, value: Either) {
46             val output = encoder as? JsonEncoder ?: throw SerializationException("This class can be saved only by Json")
47             val tree = when (value) {
48                 is Either.Left -> JsonObject(mapOf("error" to JsonPrimitive(value.errorMsg)))
49                 is Either.Right -> output.json.encodeToJsonElement(Payload.serializer(), value.data)
50             }
51 
52             output.encodeJsonElement(tree)
53         }
54     }
55 
56     @Serializable
57     data class Event(
58         val id: Int,
59         @Serializable(with = EitherSerializer::class) val payload: Either,
60         val timestamp: Long
61     )
62 
63     @Test
testParseDatanull64     fun testParseData() {
65         val ev = Json.decodeFromString(Event.serializer(), decoderData)
66         with(ev) {
67             assertEquals(0, id)
68             assertEquals(Either.Right(Payload(42, 43, "Hello world")), payload)
69             assertEquals(1000, timestamp)
70         }
71     }
72 
73     @Test
testParseErrornull74     fun testParseError() {
75         val ev = Json.decodeFromString(Event.serializer(), decoderError)
76         with(ev) {
77             assertEquals(1, id)
78             assertEquals(Either.Left("Connection timed out"), payload)
79             assertEquals(1001, timestamp)
80         }
81     }
82 
83     @Test
testWriteDatanull84     fun testWriteData() {
85         val encoderData = Event(0, Either.Right(Payload(42, 43, "Hello world")), 1000)
86         val ev = Json.encodeToString(Event.serializer(), encoderData)
87         assertEquals(decoderData, ev)
88     }
89 
90     @Test
testWriteErrornull91     fun testWriteError() {
92         val encoderError = Event(1, Either.Left("Connection timed out"), 1001)
93         val ev = Json.encodeToString(Event.serializer(), encoderError)
94         assertEquals(decoderError, ev)
95     }
96 }
97