• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2017-2023 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.*
9 import kotlin.test.*
10 
11 class TrailingCommaTest : JsonTestBase() {
12     val tj = Json { allowTrailingComma = true }
13 
14     @Serializable
15     data class Optional(val data: String = "")
16 
17     @Serializable
18     data class MultipleFields(val a: String, val b: String, val c: String)
19 
20     private val multipleFields = MultipleFields("1", "2", "3")
21 
22     @Serializable
23     data class WithMap(val m: Map<String, String>)
24 
25     private val withMap = WithMap(mapOf("a" to "1", "b" to "2", "c" to "3"))
26 
27     @Serializable
28     data class WithList(val l: List<Int>)
29 
30     private val withList = WithList(listOf(1, 2, 3))
31 
32     @Test
33     fun basic() = parametrizedTest { mode ->
34         val sd = """{"data":"str",}"""
35         assertEquals(Optional("str"), tj.decodeFromString<Optional>(sd, mode))
36     }
37 
38     @Test
39     fun trailingCommaNotAllowedByDefaultForObjects() = parametrizedTest { mode ->
40         val sd = """{"data":"str",}"""
41         checkSerializationException({
42             default.decodeFromString<Optional>(sd, mode)
43         }, { message ->
44             assertContains(
45                 message,
46                 """Unexpected JSON token at offset 13: Trailing comma before the end of JSON object"""
47             )
48         })
49     }
50 
51     @Test
52     fun trailingCommaNotAllowedByDefaultForLists() = parametrizedTest { mode ->
53         val sd = """{"l":[1,]}"""
54         checkSerializationException({
55             default.decodeFromString<WithList>(sd, mode)
56         }, { message ->
57             assertContains(
58                 message,
59                 """Unexpected JSON token at offset 7: Trailing comma before the end of JSON array"""
60             )
61         })
62     }
63 
64     @Test
65     fun trailingCommaNotAllowedByDefaultForMaps() = parametrizedTest { mode ->
66         val sd = """{"m":{"a": "b",}}"""
67         checkSerializationException({
68             default.decodeFromString<WithMap>(sd, mode)
69         }, { message ->
70             assertContains(
71                 message,
72                 """Unexpected JSON token at offset 14: Trailing comma before the end of JSON object"""
73             )
74         })
75     }
76 
77     @Test
78     fun emptyObjectNotAllowed() = parametrizedTest { mode ->
79         assertFailsWithMessage<SerializationException>("Unexpected leading comma") {
80             tj.decodeFromString<Optional>("""{,}""", mode)
81         }
82     }
83 
84     @Test
85     fun emptyListNotAllowed() = parametrizedTest { mode ->
86         assertFailsWithMessage<SerializationException>("Unexpected leading comma") {
87             tj.decodeFromString<WithList>("""{"l":[,]}""", mode)
88         }
89     }
90 
91     @Test
92     fun emptyMapNotAllowed() = parametrizedTest { mode ->
93         assertFailsWithMessage<SerializationException>("Unexpected leading comma") {
94             tj.decodeFromString<WithMap>("""{"m":{,}}""", mode)
95         }
96     }
97 
98     @Test
99     fun testMultipleFields() = parametrizedTest { mode ->
100         val input = """{"a":"1","b":"2","c":"3", }"""
101         assertEquals(multipleFields, tj.decodeFromString(input, mode))
102     }
103 
104     @Test
105     fun testWithMap() = parametrizedTest { mode ->
106         val input = """{"m":{"a":"1","b":"2","c":"3", }}"""
107 
108         assertEquals(withMap, tj.decodeFromString(input, mode))
109     }
110 
111     @Test
112     fun testWithList() = parametrizedTest { mode ->
113         val input = """{"l":[1, 2, 3, ]}"""
114         assertEquals(withList, tj.decodeFromString(input, mode))
115     }
116 
117     @Serializable
118     data class Mixed(val mf: MultipleFields, val wm: WithMap, val wl: WithList)
119 
120     @Test
121     fun testMixed() = parametrizedTest { mode ->
122         //language=JSON5
123         val input = """{"mf":{"a":"1","b":"2","c":"3",},
124             "wm":{"m":{"a":"1","b":"2","c":"3",},},
125             "wl":{"l":[1, 2, 3,],},}"""
126         assertEquals(Mixed(multipleFields, withMap, withList), tj.decodeFromString(input, mode))
127     }
128 }
129