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.descriptors.* 8 import kotlinx.serialization.encoding.* 9 import kotlinx.serialization.* 10 import kotlinx.serialization.modules.* 11 import kotlinx.serialization.test.* 12 import kotlin.test.* 13 import kotlin.test.assertFailsWith 14 15 class DecodeFromDynamicTest { 16 @Serializable 17 data class Data(val a: Int) 18 19 @Serializable 20 data class DataWrapper(val s: String, val d: Data?) 21 22 @Serializable 23 data class DataWrapperOptional(val s: String,val d: Data? = null) 24 25 @Serializable 26 data class IntList(val l: List<Int>) 27 28 @Serializable 29 data class ListOfLists(val l: List<List<Data>>) 30 31 @Serializable 32 data class MapWrapper(val m: Map<String, Int>) 33 34 @Serializable 35 data class ComplexMapWrapper(val m: Map<String, Data>) 36 37 @Serializable 38 data class IntMapWrapper(val m: Map<Int, Int>) 39 40 @Serializable 41 data class WithChar(val a: Char) 42 43 @Serializable 44 data class AllTypes( 45 val b: Byte, 46 val s: Short, 47 val i: Int, 48 val f: Float, 49 val d: Double, 50 val c: Char, 51 val B: Boolean, 52 val S: String 53 ) 54 55 @Serializable 56 data class NonTrivialMap(val m: Map<String, Char>) 57 58 data class NotDefault(val a: Int) 59 60 object NDSerializer : KSerializer<NotDefault> { <lambda>null61 override val descriptor = buildClassSerialDescriptor("notDefault") { 62 element<Int>("a") 63 } 64 serializenull65 override fun serialize(encoder: Encoder, value: NotDefault) { 66 encoder.encodeInt(value.a) 67 } 68 deserializenull69 override fun deserialize(decoder: Decoder): NotDefault { 70 return NotDefault(decoder.decodeInt()) 71 } 72 } 73 74 @Serializable 75 data class NDWrapper(@Contextual val data: NotDefault) 76 77 @Test dynamicSimpleTestnull78 fun dynamicSimpleTest() { 79 val dyn = js("{a: 42}") 80 val parsed = Json.decodeFromDynamic(Data.serializer(), dyn) 81 assertEquals(Data(42), parsed) 82 83 val dyn2 = js("{a: 'a'}") 84 val parsed2 = Json.decodeFromDynamic(WithChar.serializer(), dyn2) 85 assertEquals(WithChar('a'), parsed2) 86 87 val dyn3 = js("{a: 97}") 88 val parsed3 = Json.decodeFromDynamic(WithChar.serializer(), dyn3) 89 assertEquals(WithChar('a'), parsed3) 90 } 91 92 @Test dynamicAllTypesTestnull93 fun dynamicAllTypesTest() { 94 val dyn = js("""{ b: 1, s: 2, i: 3, f: 1.0, d: 42.0, c: 'a', B: true, S: "str"}""") 95 val kotlinObj = AllTypes(1, 2, 3, 1.0f, 42.0, 'a', true, "str") 96 97 assertEquals(kotlinObj, Json.decodeFromDynamic(AllTypes.serializer(), dyn)) 98 } 99 100 @Test dynamicNestedTestnull101 fun dynamicNestedTest() { 102 val dyn = js("""{s:"foo", d:{a:42}}""") 103 val parsed = Json.decodeFromDynamic(DataWrapper.serializer(), dyn) 104 val expected = DataWrapper("foo", Data(42)) 105 assertEquals(expected, parsed) 106 assertEquals(3, parsed.s.length) 107 assertFailsWith(ClassCastException::class) { dyn as DataWrapper } 108 } 109 110 @Test dynamicNullableTestnull111 fun dynamicNullableTest() { 112 val dyn1 = js("""({s:"foo", d: null})""") 113 val dyn2 = js("""({s:"foo"})""") 114 val dyn3 = js("""({s:"foo", d: undefined})""") 115 116 assertEquals(DataWrapper("foo", null), Json.decodeFromDynamic(DataWrapper.serializer(), dyn1)) 117 assertFailsWithMissingField { 118 Json.decodeFromDynamic( 119 DataWrapper.serializer(), 120 dyn2 121 ) 122 } 123 assertFailsWithMissingField { 124 Json.decodeFromDynamic( 125 DataWrapper.serializer(), 126 dyn3 127 ) 128 } 129 } 130 131 @Test dynamicOptionalTestnull132 fun dynamicOptionalTest() { 133 val dyn1 = js("""({s:"foo", d: null})""") 134 val dyn2 = js("""({s:"foo"})""") 135 val dyn3 = js("""({s:"foo", d: undefined})""") 136 137 assertEquals( 138 DataWrapperOptional("foo", null), 139 Json.decodeFromDynamic(DataWrapperOptional.serializer(), dyn1) 140 ) 141 assertEquals( 142 DataWrapperOptional("foo", null), 143 Json.decodeFromDynamic(DataWrapperOptional.serializer(), dyn2) 144 ) 145 assertEquals( 146 DataWrapperOptional("foo", null), 147 Json.decodeFromDynamic(DataWrapperOptional.serializer(), dyn3) 148 ) 149 } 150 151 @Test dynamicListTestnull152 fun dynamicListTest() { 153 val dyn1 = js("""({l:[1,2]})""") 154 val dyn2 = js("""({l:[[],[{a:42}]]})""") 155 156 assertEquals(IntList(listOf(1, 2)), Json.decodeFromDynamic(IntList.serializer(), dyn1)) 157 assertEquals( 158 ListOfLists(listOf(listOf(), listOf(Data(42)))), 159 Json.decodeFromDynamic(ListOfLists.serializer(), dyn2) 160 ) 161 } 162 163 @Test dynamicMapTestnull164 fun dynamicMapTest() { 165 val dyn = js("({m : {\"a\": 1, \"b\" : 2}})") 166 val m = MapWrapper(mapOf("a" to 1, "b" to 2)) 167 assertEquals(m, Json.decodeFromDynamic(MapWrapper.serializer(), dyn)) 168 } 169 170 @Test testFunnyMapnull171 fun testFunnyMap() { 172 val dyn = js("({m: {\"a\": 'b', \"b\" : 'a'}})") 173 val m = NonTrivialMap(mapOf("a" to 'b', "b" to 'a')) 174 assertEquals(m, Json.decodeFromDynamic(NonTrivialMap.serializer(), dyn)) 175 } 176 177 @Test dynamicMapComplexTestnull178 fun dynamicMapComplexTest() { 179 val dyn = js("({m: {1: {a: 42}, 2: {a: 43}}})") 180 val m = ComplexMapWrapper(mapOf("1" to Data(42), "2" to Data(43))) 181 assertEquals(m, Json.decodeFromDynamic(ComplexMapWrapper.serializer(), dyn)) 182 } 183 184 @Test testIntMapTestnull185 fun testIntMapTest() { 186 val dyn = js("({m: {1: 2, 3: 4}})") 187 val m = IntMapWrapper(mapOf(1 to 2, 3 to 4)) 188 assertEquals(m, Json.decodeFromDynamic(IntMapWrapper.serializer(), dyn)) 189 } 190 191 @Test parseWithCustomSerializersnull192 fun parseWithCustomSerializers() { 193 val json = Json { serializersModule = serializersModuleOf(NotDefault::class, NDSerializer) } 194 val dyn1 = js("({data: 42})") 195 assertEquals(NDWrapper(NotDefault(42)), 196 json.decodeFromDynamic(NDWrapper.serializer(), dyn1) 197 ) 198 } 199 200 } 201