@@ -2,8 +2,11 @@ package io.github.json5.kotlin
22
33import io.kotest.assertions.throwables.shouldThrow
44import io.kotest.matchers.shouldBe
5+ import io.kotest.matchers.types.shouldBeInstanceOf
56import org.junit.jupiter.api.Test
67import org.junit.jupiter.api.DisplayName
8+ import kotlin.Double.Companion.NaN
9+ import kotlin.test.assertTrue
710
811@DisplayName(" JSON5.parse" )
912class JSON5ParseTest {
@@ -43,6 +46,227 @@ class JSON5ParseTest {
4346 JSON5 .parse(""" [1, "string", true, null]""" ) shouldBe listOf (1.0 , " string" , true , null )
4447 }
4548
49+ // Additional object tests
50+
51+ @Test
52+ fun `should parse double quoted string property names` () {
53+ JSON5 .parse(""" {"a":1}""" ) shouldBe mapOf (" a" to 1.0 )
54+ }
55+
56+ @Test
57+ fun `should parse single quoted string property names` () {
58+ JSON5 .parse(""" {'a':1}""" ) shouldBe mapOf (" a" to 1.0 )
59+ }
60+
61+ @Test
62+ fun `should parse unquoted property names` () {
63+ JSON5 .parse(""" {a:1}""" ) shouldBe mapOf (" a" to 1.0 )
64+ }
65+
66+ @Test
67+ fun `should parse special character property names` () {
68+ JSON5 .parse(""" {\$\_:1,_$:2,a\u200C:3}""" ) shouldBe mapOf (" \$ _" to 1.0 , " _$" to 2.0 , " a\u200C " to 3.0 )
69+ }
70+
71+ @Test
72+ fun `should parse unicode property names` () {
73+ JSON5 .parse(""" {ùńîċõďë:9}""" ) shouldBe mapOf (" ùńîċõďë" to 9.0 )
74+ }
75+
76+ @Test
77+ fun `should parse escaped property names` () {
78+ JSON5 .parse(""" {\\u0061\\u0062:1,\\u0024\\u005F:2,\\u005F\\u0024:3}""" ) shouldBe mapOf (" ab" to 1.0 , " \$ _" to 2.0 , " _$" to 3.0 )
79+ }
80+
81+ @Test
82+ fun `should preserve __proto__ property names` () {
83+ val result = JSON5 .parse(""" {"__proto__":1}""" ) as Map <* , * >
84+ result[" __proto__" ] shouldBe 1.0
85+ }
86+
87+ @Test
88+ fun `should parse multiple properties` () {
89+ JSON5 .parse(""" {abc:1,def:2}""" ) shouldBe mapOf (" abc" to 1.0 , " def" to 2.0 )
90+ }
91+
92+ @Test
93+ fun `should parse nested objects` () {
94+ JSON5 .parse(""" {a:{b:2}}""" ) shouldBe mapOf (" a" to mapOf (" b" to 2.0 ))
95+ }
96+
97+ // Additional array tests
98+
99+ @Test
100+ fun `should parse multiple array values` () {
101+ JSON5 .parse(" [1,2]" ) shouldBe listOf (1.0 , 2.0 )
102+ }
103+
104+ @Test
105+ fun `should parse nested arrays` () {
106+ JSON5 .parse(" [1,[2,3]]" ) shouldBe listOf (1.0 , listOf (2.0 , 3.0 ))
107+ }
108+
109+ // Number tests
110+
111+ @Test
112+ fun `should parse leading zeroes` () {
113+ JSON5 .parse(" [0,0.,0e0]" ) shouldBe listOf (0.0 , 0.0 , 0.0 )
114+ }
115+
116+ @Test
117+ fun `should parse integers` () {
118+ JSON5 .parse(" [1,23,456,7890]" ) shouldBe listOf (1.0 , 23.0 , 456.0 , 7890.0 )
119+ }
120+
121+ @Test
122+ fun `should parse signed numbers` () {
123+ JSON5 .parse(" [-1,+2,-.1,-0]" ) shouldBe listOf (- 1.0 , 2.0 , - 0.1 , - 0.0 )
124+ }
125+
126+ @Test
127+ fun `should parse leading decimal points` () {
128+ JSON5 .parse(" [.1,.23]" ) shouldBe listOf (0.1 , 0.23 )
129+ }
130+
131+ @Test
132+ fun `should parse fractional numbers` () {
133+ JSON5 .parse(" [1.0,1.23]" ) shouldBe listOf (1.0 , 1.23 )
134+ }
135+
136+ @Test
137+ fun `should parse exponents` () {
138+ JSON5 .parse(" [1e0,1e1,1e01,1.e0,1.1e0,1e-1,1e+1]" ) shouldBe
139+ listOf (1.0 , 10.0 , 10.0 , 1.0 , 1.1 , 0.1 , 10.0 )
140+ }
141+
142+ @Test
143+ fun `should parse hexadecimal numbers` () {
144+ JSON5 .parse(" [0x1,0x10,0xff,0xFF]" ) shouldBe listOf (1.0 , 16.0 , 255.0 , 255.0 )
145+ }
146+
147+ @Test
148+ fun `should parse infinity values` () {
149+ JSON5 .parse(" [Infinity,-Infinity]" ) shouldBe listOf (Double .POSITIVE_INFINITY , Double .NEGATIVE_INFINITY )
150+ }
151+
152+ @Test
153+ fun `should parse NaN` () {
154+ val result = JSON5 .parse(" NaN" )
155+ result.shouldBeInstanceOf<Double >()
156+ assertTrue((result as Double ).isNaN())
157+ }
158+
159+ @Test
160+ fun `should parse signed NaN` () {
161+ val result = JSON5 .parse(" -NaN" )
162+ result.shouldBeInstanceOf<Double >()
163+ assertTrue((result as Double ).isNaN())
164+ }
165+
166+ @Test
167+ fun `should parse bare numbers` () {
168+ JSON5 .parse(" 1" ) shouldBe 1.0
169+ JSON5 .parse(" +1.23e100" ) shouldBe 1 .23e100
170+ }
171+
172+ @Test
173+ fun `should parse bare hexadecimal numbers` () {
174+ JSON5 .parse(" 0x1" ) shouldBe 1.0
175+ JSON5 .parse(" -0x0123456789abcdefABCDEF" ) shouldBe - 0x0123456789abcdefL .toDouble()
176+ }
177+
178+ // String tests
179+
180+ @Test
181+ fun `should parse double quoted strings` () {
182+ JSON5 .parse(" \" abc\" " ) shouldBe " abc"
183+ }
184+
185+ @Test
186+ fun `should parse single quoted strings` () {
187+ JSON5 .parse(" 'abc'" ) shouldBe " abc"
188+ }
189+
190+ @Test
191+ fun `should parse quotes in strings` () {
192+ JSON5 .parse(""" ['"',"'"]""" ) shouldBe listOf (" \" " , " '" )
193+ }
194+
195+ @Test
196+ fun `should parse escaped characters` () {
197+ JSON5 .parse(""" '\\b\\f\\n\\r\\t\\v\\0\\x0f\\u01fF\\\n\\\r\n\\\r\\\u2028\\\u2029\\a\\\'\\\"'""" ) shouldBe
198+ " \b\u000C \n\r\t \u000B\u0000\u000F\u01FF\u0007 '\" "
199+ }
200+
201+ @Test
202+ fun `should parse line and paragraph separators` () {
203+ JSON5 .parse(" '\u2028\u2029 '" ) shouldBe " \u2028\u2029 "
204+ }
205+
206+ // Comments tests
207+
208+ @Test
209+ fun `should parse single-line comments` () {
210+ JSON5 .parse(" {//comment\n }" ) shouldBe emptyMap<String , Any ?>()
211+ }
212+
213+ @Test
214+ fun `should parse single-line comments at end of input` () {
215+ JSON5 .parse(" {}//comment" ) shouldBe emptyMap<String , Any ?>()
216+ }
217+
218+ @Test
219+ fun `should parse multi-line comments` () {
220+ JSON5 .parse(" {/*comment\n ** */}" ) shouldBe emptyMap<String , Any ?>()
221+ }
222+
223+ // Whitespace tests
224+
225+ @Test
226+ fun `should parse whitespace` () {
227+ JSON5 .parse(" {\t \u000B\u000C \u00A0\uFEFF \n\r \u2028\u2029\u2003 }" ) shouldBe emptyMap<String , Any ?>()
228+ }
229+
230+ // Reviver tests
231+
232+ @Test
233+ fun `should modify property values using reviver` () {
234+ JSON5 .parse(" {a:1,b:2}" ) { k, v -> if (k == " a" ) " revived" else v } shouldBe mapOf (" a" to " revived" , " b" to 2.0 )
235+ }
236+
237+ @Test
238+ fun `should modify nested object property values using reviver` () {
239+ JSON5 .parse(" {a:{b:2}}" ) { k, v -> if (k == " b" ) " revived" else v } shouldBe mapOf (" a" to mapOf (" b" to " revived" ))
240+ }
241+
242+ @Test
243+ fun `should delete property values using reviver` () {
244+ JSON5 .parse(" {a:1,b:2}" ) { k, v -> if (k == " a" ) null else v } shouldBe mapOf (" b" to 2.0 )
245+ }
246+
247+ @Test
248+ fun `should modify array values using reviver` () {
249+ JSON5 .parse(" [0,1,2]" ) { k, v -> if (k == " 1" ) " revived" else v } shouldBe listOf (0.0 , " revived" , 2.0 )
250+ }
251+
252+ @Test
253+ fun `should modify nested array values using reviver` () {
254+ JSON5 .parse(" [0,[1,2,3]]" ) { k, v -> if (k == " 2" ) " revived" else v } shouldBe listOf (0.0 , listOf (1.0 , 2.0 , " revived" ))
255+ }
256+
257+ @Test
258+ fun `should delete array values using reviver` () {
259+ val result = JSON5 .parse(" [0,1,2]" ) { k, v -> if (k == " 1" ) null else v } as List <* >
260+ result[0 ] shouldBe 0.0
261+ result[1 ] shouldBe null
262+ result[2 ] shouldBe 2.0
263+ }
264+
265+ @Test
266+ fun `should modify the root value using reviver` () {
267+ JSON5 .parse(" 1" ) { k, v -> if (k == " " ) " revived" else v } shouldBe " revived"
268+ }
269+
46270 @Test
47271 fun `should throw exception for invalid JSON5` () {
48272 val exception = shouldThrow<JSON5Exception > {
0 commit comments