• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2017-2021 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.test.assertFailsWithSerial
9 import kotlin.test.*
10 
11 class JsonCoerceInputValuesTest : JsonTestBase() {
12     @Serializable
13     data class WithBoolean(val b: Boolean = false)
14 
15     @Serializable
16     data class WithEnum(val e: SampleEnum = SampleEnum.OptionC)
17 
18     @Serializable
19     data class MultipleValues(
20         val data: StringData,
21         val data2: IntData = IntData(0),
22         val i: Int = 42,
23         val e: SampleEnum = SampleEnum.OptionA,
24         val foo: String
25     )
26 
27     @Serializable
28     data class NullableEnumHolder(
29         val enum: SampleEnum?
30     )
31 
32     @Serializable
33     class Uncoercable(
34         val s: String
35     )
36 
37     @Serializable
38     class UncoercableEnum(
39         val e: SampleEnum
40     )
41 
42     val json = Json {
43         coerceInputValues = true
44         isLenient = true
45     }
46 
47     private fun <T> doTest(inputs: List<String>, expected: T, serializer: KSerializer<T>) {
48         for (input in inputs) {
49             parametrizedTest(json) {
50                 assertEquals(expected, decodeFromString(serializer, input), "Failed on input: $input")
51             }
52         }
53     }
54 
55     @Test
56     fun testUseDefaultOnNonNullableBoolean() = doTest(
57         listOf(
58             """{"b":false}""",
59             """{"b":null}""",
60             """{}""",
61         ),
62         WithBoolean(),
63         WithBoolean.serializer()
64     )
65 
66     @Test
67     fun testUseDefaultOnUnknownEnum() {
68         doTest(
69             listOf(
70                 """{"e":unknown_value}""",
71                 """{"e":"unknown_value"}""",
72                 """{"e":null}""",
73                 """{}""",
74             ),
75             WithEnum(),
76             WithEnum.serializer()
77         )
78         assertFailsWithSerial("JsonDecodingException") {
79             json.decodeFromString(WithEnum.serializer(), """{"e":{"x":"definitely not a valid enum value"}}""")
80         }
81         assertFailsWithSerial("JsonDecodingException") { // test user still sees exception on missing quotes
82             Json(json) { isLenient = false }.decodeFromString(WithEnum.serializer(), """{"e":unknown_value}""")
83         }
84     }
85 
86     @Test
87     fun testUseDefaultInMultipleCases() {
88         val testData = mapOf(
89             """{"data":{"data":"foo"},"data2":null,"i":null,"e":null,"foo":"bar"}""" to MultipleValues(
90                 StringData("foo"),
91                 foo = "bar"
92             ),
93             """{"data":{"data":"foo"},"data2":{"intV":42},"i":null,"e":null,"foo":"bar"}""" to MultipleValues(
94                 StringData(
95                     "foo"
96                 ), IntData(42), foo = "bar"
97             ),
98             """{"data":{"data":"foo"},"data2":{"intV":42},"i":0,"e":"NoOption","foo":"bar"}""" to MultipleValues(
99                 StringData("foo"),
100                 IntData(42),
101                 i = 0,
102                 foo = "bar"
103             ),
104             """{"data":{"data":"foo"},"data2":{"intV":42},"i":0,"e":"OptionC","foo":"bar"}""" to MultipleValues(
105                 StringData("foo"),
106                 IntData(42),
107                 i = 0,
108                 e = SampleEnum.OptionC,
109                 foo = "bar"
110             ),
111         )
112         for ((input, expected) in testData) {
113             assertEquals(expected, json.decodeFromString(MultipleValues.serializer(), input), "Failed on input: $input")
114         }
115     }
116 
117     @Test
118     fun testNullSupportForEnums() = parametrizedTest(json) {
119         var decoded = decodeFromString<NullableEnumHolder>("""{"enum": null}""")
120         assertNull(decoded.enum)
121 
122         decoded = decodeFromString<NullableEnumHolder>("""{"enum": OptionA}""")
123         assertEquals(SampleEnum.OptionA, decoded.enum)
124     }
125 
126     @Test
127     fun propertiesWithoutDefaultValuesDoNotChangeErrorMsg() {
128         val json2 = Json(json) { coerceInputValues = false }
129         parametrizedTest { mode ->
130             val e1 = assertFailsWith<SerializationException>() { json.decodeFromString<Uncoercable>("""{"s":null}""", mode) }
131             val e2 = assertFailsWith<SerializationException>() { json2.decodeFromString<Uncoercable>("""{"s":null}""", mode) }
132             assertEquals(e2.message, e1.message)
133         }
134     }
135 
136     @Test
137     fun propertiesWithoutDefaultValuesDoNotChangeErrorMsgEnum() {
138         val json2 = Json(json) { coerceInputValues = false }
139         parametrizedTest { mode ->
140             val e1 = assertFailsWith<SerializationException> { json.decodeFromString<UncoercableEnum>("""{"e":"UNEXPECTED"}""", mode) }
141             val e2 = assertFailsWith<SerializationException> { json2.decodeFromString<UncoercableEnum>("""{"e":"UNEXPECTED"}""", mode) }
142             assertEquals(e2.message, e1.message)
143         }
144     }
145 }
146