summaryrefslogtreecommitdiff
path: root/runtime/common/src/testWithNative/kotlinx/serialization/features/ContextAndPolymorphicTest.kt
blob: 53259bbc3a78dba42d8bebaa55f6c00ede5de8b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.serialization.features

import kotlinx.serialization.*
import kotlinx.serialization.internal.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
import kotlin.test.*

class ContextAndPolymorphicTest {

    @Serializable
    data class Data(val a: Int, val b: Int = 42)

    @Serializable
    data class EnhancedData(
        val data: Data,
        @ContextualSerialization val stringPayload: Payload,
        @Serializable(with = BinaryPayloadSerializer::class) val binaryPayload: Payload
    )

    @Serializable
    data class Payload(val s: String)

    @Serializable
    data class PayloadList(val ps: List<@ContextualSerialization Payload>)

    @Serializer(forClass = Payload::class)
    object PayloadSerializer {}

    object BinaryPayloadSerializer : KSerializer<Payload> {
        override val descriptor: SerialDescriptor = SerialClassDescImpl("Payload")

        override fun serialize(encoder: Encoder, obj: Payload) {
            encoder.encodeString(HexConverter.printHexBinary(obj.s.toUtf8Bytes()))
        }

        override fun deserialize(decoder: Decoder): Payload {
            return Payload(stringFromUtf8Bytes(HexConverter.parseHexBinary(decoder.decodeString())))
        }
    }

    private val obj = EnhancedData(Data(100500), Payload("string"), Payload("binary"))
    private lateinit var json: Json

    @BeforeTest
    fun initContext() {
        val scope = serializersModuleOf(Payload::class, PayloadSerializer)
        val bPolymorphicModule = SerializersModule { polymorphic(Any::class) { Payload::class with PayloadSerializer } }
        json = Json(
            JsonConfiguration(unquoted = true, useArrayPolymorphism = true),
            context = scope + bPolymorphicModule
        )
    }

    @Test
    fun testWriteCustom() {
        val s = json.stringify(EnhancedData.serializer(), obj)
        assertEquals("{data:{a:100500,b:42},stringPayload:{s:string},binaryPayload:62696E617279}", s)
    }

    @Test
    fun testReadCustom() {
        val s = json.parse(EnhancedData.serializer(), "{data:{a:100500,b:42},stringPayload:{s:string},binaryPayload:62696E617279}")
        assertEquals(obj, s)
    }

    @Test
    fun testWriteCustomList() {
        val s = json.stringify(PayloadList.serializer(), PayloadList(listOf(Payload("1"), Payload("2"))))
        assertEquals("{ps:[{s:1},{s:2}]}", s)
    }

    @Test
    fun testPolymorphicResolve() {
        val map = mapOf<String, Any>("Payload" to Payload("data"))
        val serializer = (StringSerializer to PolymorphicSerializer(Any::class)).map
        val s = json.stringify(serializer, map)
        assertEquals("""{Payload:[kotlinx.serialization.features.ContextAndPolymorphicTest.Payload,{s:data}]}""", s)
    }

    @Test
    fun testDifferentRepresentations() {
        val simpleModule = serializersModule(PayloadSerializer)
        // MapModule and CompositeModule are also available
        val binaryModule = serializersModule(BinaryPayloadSerializer)

        val json1 = Json { useArrayPolymorphism = true; serialModule = simpleModule }
        val json2 = Json { useArrayPolymorphism = true; serialModule = binaryModule }

        // in json1, Payload would be serialized with PayloadSerializer,
        // in json2, Payload would be serialized with BinaryPayloadSerializer

        val list = PayloadList(listOf(Payload("string")))
        assertEquals("""{"ps":[{"s":"string"}]}""", json1.stringify(PayloadList.serializer(), list))
        assertEquals("""{"ps":["737472696E67"]}""", json2.stringify(PayloadList.serializer(), list))
    }
}