• 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.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