• 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 @file:Suppress("ReplaceArrayOfWithLiteral") // https://youtrack.jetbrains.com/issue/KT-22578
6 
7 package kotlinx.serialization.features
8 
9 import kotlinx.serialization.*
10 import kotlinx.serialization.json.*
11 import kotlinx.serialization.test.*
12 import kotlin.test.*
13 
14 class JsonNamesTest : JsonTestBase() {
15 
16     @Serializable
17     data class WithNames(@JsonNames("foo", "_foo") val data: String)
18 
19     @Serializable
20     enum class AlternateEnumNames {
21         @JsonNames("someValue", "some_value")
22         VALUE_A,
23         VALUE_B
24     }
25 
26     @Serializable
27     data class WithEnumNames(
28         val enumList: List<AlternateEnumNames>,
29         val checkCoercion: AlternateEnumNames = AlternateEnumNames.VALUE_B
30     )
31 
32     @Serializable
33     data class CollisionWithAlternate(
34         @JsonNames("_foo") val data: String,
35         @JsonNames("_foo") val foo: String
36     )
37 
38     private val inputString1 = """{"foo":"foo"}"""
39     private val inputString2 = """{"_foo":"foo"}"""
40 
41     private fun parameterizedCoercingTest(test: (json: Json, streaming: JsonTestingMode, msg: String) -> Unit) {
42         for (coercing in listOf(true, false)) {
43             val json = Json {
44                 coerceInputValues = coercing
45                 useAlternativeNames = true
46             }
47             parametrizedTest { streaming ->
48                 test(
49                     json, streaming,
50                     "Failed test with coercing=$coercing and streaming=$streaming"
51                 )
52             }
53         }
54     }
55 
56     @Test
57     fun testEnumSupportsAlternativeNames() {
58         val input = """{"enumList":["VALUE_A", "someValue", "some_value", "VALUE_B"], "checkCoercion":"someValue"}"""
59         val expected = WithEnumNames(
60             listOf(
61                 AlternateEnumNames.VALUE_A,
62                 AlternateEnumNames.VALUE_A,
63                 AlternateEnumNames.VALUE_A,
64                 AlternateEnumNames.VALUE_B
65             ), AlternateEnumNames.VALUE_A
66         )
67         parameterizedCoercingTest { json, streaming, msg ->
68             assertEquals(expected, json.decodeFromString(input, streaming), msg)
69         }
70     }
71 
72     @Test
73     fun topLevelEnumSupportAlternativeNames() {
74         parameterizedCoercingTest { json, streaming, msg ->
75             assertEquals(AlternateEnumNames.VALUE_A, json.decodeFromString("\"someValue\"", streaming), msg)
76         }
77     }
78 
79     @Test
80     fun testParsesAllAlternativeNames() {
81         for (input in listOf(inputString1, inputString2)) {
82             parameterizedCoercingTest { json, streaming, _ ->
83                 val data = json.decodeFromString(WithNames.serializer(), input, jsonTestingMode = streaming)
84                 assertEquals("foo", data.data, "Failed to parse input '$input' with streaming=$streaming")
85             }
86         }
87     }
88 
89     @Test
90     fun testThrowsAnErrorOnDuplicateNames() {
91         val serializer = CollisionWithAlternate.serializer()
92         parameterizedCoercingTest { json, streaming, _ ->
93             assertFailsWithMessage<SerializationException>(
94                 """The suggested name '_foo' for property foo is already one of the names for property data""",
95                 "Class ${serializer.descriptor.serialName} did not fail with streaming=$streaming"
96             ) {
97                 json.decodeFromString(
98                     serializer, inputString2,
99                     jsonTestingMode = streaming
100                 )
101             }
102         }
103     }
104 }
105