11package org.json5.app
22
33import dev.hossain.json5kt.JSON5
4+ import dev.hossain.json5kt.JSON5Value
5+ import kotlinx.serialization.Serializable
46
57/* *
68 * Main application entry point for testing JSON5 parsing and serialization.
@@ -37,6 +39,13 @@ fun main() {
3739
3840 // Test serialization and deserialization of Employee model
3941 testEmployeeSerialization()
42+
43+ // Run README sample code validation tests
44+ println (" \n === README Sample Code Validation ===" )
45+ testBasicParsingAndStringifying()
46+ testKotlinxSerializationIntegration()
47+ testAdvancedFeatures()
48+ testMigrationCompatibility()
4049}
4150
4251
@@ -59,4 +68,219 @@ fun testEmployeeSerialization() {
5968 } else {
6069 println (" ⚠️ Error: Could not find resource: $fileName " )
6170 }
71+ }
72+
73+ /* *
74+ * Tests basic parsing and stringifying functionality from README
75+ */
76+ fun testBasicParsingAndStringifying () {
77+ println (" \n --- Testing Basic Parsing and Stringifying ---" )
78+
79+ try {
80+ // Parse JSON5 to strongly-typed JSON5Value objects
81+ val json5 = """
82+ {
83+ // Configuration for my app
84+ name: 'MyApp',
85+ version: 2,
86+ features: ['auth', 'analytics',], // trailing comma
87+ }
88+ """ .trimIndent()
89+
90+ val parsed = JSON5 .parse(json5)
91+ println (" ✓ Parsed JSON5 successfully: $parsed " )
92+
93+ // Access values in a type-safe way
94+ when (parsed) {
95+ is JSON5Value .Object -> {
96+ val name = parsed.value[" name" ] as ? JSON5Value .String
97+ val version = parsed.value[" version" ] as ? JSON5Value .Number
98+ val features = parsed.value[" features" ] as ? JSON5Value .Array
99+
100+ println (" ✓ App name: ${name?.value} " ) // "MyApp"
101+ println (" ✓ Version: ${(version as ? JSON5Value .Number .Integer )?.value ? : (version as ? JSON5Value .Number .Decimal )?.value?.toInt()} " ) // 2
102+ println (" ✓ Features: ${features?.value?.map { (it as JSON5Value .String ).value }} " ) // ["auth", "analytics"]
103+ }
104+ else -> println (" Parsed value is not an object" )
105+ }
106+
107+ // Stringify Kotlin objects to JSON5
108+ val data = mapOf (
109+ " name" to " MyApp" ,
110+ " version" to 2 ,
111+ " enabled" to true
112+ )
113+ val json5String = JSON5 .stringify(data)
114+ println (" ✓ Stringified to JSON5: $json5String " )
115+
116+ } catch (e: Exception ) {
117+ println (" ⚠️ Error in basic parsing and stringifying test: ${e.message} " )
118+ e.printStackTrace()
119+ }
120+ }
121+
122+ /* *
123+ * Tests kotlinx.serialization integration from README
124+ */
125+ fun testKotlinxSerializationIntegration () {
126+ println (" \n --- Testing kotlinx.serialization Integration ---" )
127+
128+ try {
129+ @Serializable
130+ data class Config (
131+ val appName : String ,
132+ val version : Int ,
133+ val features : List <String >,
134+ val settings : Map <String , String >
135+ )
136+
137+ // Serialize to JSON5
138+ val config = Config (
139+ appName = " MyApp" ,
140+ version = 2 ,
141+ features = listOf (" auth" , " analytics" ),
142+ settings = mapOf (" theme" to " dark" , " lang" to " en" )
143+ )
144+
145+ val json5 = JSON5 .encodeToString(Config .serializer(), config)
146+ println (" ✓ Serialized to JSON5: $json5 " )
147+
148+ // Deserialize from JSON5 (with comments and formatting)
149+ val json5WithComments = """
150+ {
151+ // Application configuration
152+ appName: 'MyApp',
153+ version: 2, // current version
154+ features: [
155+ 'auth',
156+ 'analytics', // trailing comma OK
157+ ],
158+ settings: {
159+ theme: 'dark',
160+ lang: 'en',
161+ }
162+ }
163+ """ .trimIndent()
164+
165+ val decoded = JSON5 .decodeFromString(Config .serializer(), json5WithComments)
166+ println (" ✓ Deserialized from JSON5 with comments: $decoded " )
167+
168+ } catch (e: Exception ) {
169+ println (" ⚠️ Error in kotlinx.serialization integration test: ${e.message} " )
170+ e.printStackTrace()
171+ }
172+ }
173+
174+ /* *
175+ * Tests advanced features from README
176+ */
177+ fun testAdvancedFeatures () {
178+ println (" \n --- Testing Advanced Features ---" )
179+
180+ try {
181+ // JSON5 supports various number formats
182+ val numbers = JSON5 .parse("""
183+ {
184+ hex: 0xDECAF,
185+ leadingDot: .8675309,
186+ trailingDot: 8675309.,
187+ positiveSign: +1,
188+ scientific: 6.02e23,
189+ infinity: Infinity,
190+ negativeInfinity: -Infinity,
191+ notANumber: NaN
192+ }
193+ """ .trimIndent())
194+
195+ println (" ✓ Parsed numbers JSON5 successfully: $numbers " )
196+
197+ // Access different number types
198+ when (numbers) {
199+ is JSON5Value .Object -> {
200+ val hex = numbers.value[" hex" ] as ? JSON5Value .Number
201+ val infinity = numbers.value[" infinity" ] as ? JSON5Value .Number .PositiveInfinity
202+ val nan = numbers.value[" notANumber" ] as ? JSON5Value .Number .NaN
203+
204+ println (" ✓ Hex value: ${(hex as ? JSON5Value .Number .Hexadecimal )?.value ? : (hex as ? JSON5Value .Number .Decimal )?.value?.toLong()} " ) // 912559
205+ println (" ✓ Is infinity: ${infinity != null } " ) // true
206+ println (" ✓ Is NaN: ${nan != null } " ) // true
207+ }
208+ else -> println (" Numbers value is not an object" )
209+ }
210+
211+ // Multi-line strings and comments
212+ val complex = JSON5 .parse("""
213+ {
214+ multiLine: "This is a \
215+ multi-line string",
216+ /* Block comment
217+ spanning multiple lines */
218+ singleQuoted: 'Can contain "double quotes"',
219+ unquoted: 'keys work too'
220+ }
221+ """ .trimIndent())
222+
223+ println (" ✓ Parsed complex JSON5 successfully: $complex " )
224+
225+ // Working with the parsed result
226+ when (complex) {
227+ is JSON5Value .Object -> {
228+ val multiLine = complex.value[" multiLine" ] as ? JSON5Value .String
229+ val singleQuoted = complex.value[" singleQuoted" ] as ? JSON5Value .String
230+
231+ println (" ✓ Multi-line: ${multiLine?.value} " )
232+ println (" ✓ Single quoted: ${singleQuoted?.value} " )
233+ }
234+ else -> println (" Complex value is not an object" )
235+ }
236+
237+ } catch (e: Exception ) {
238+ println (" ⚠️ Error in advanced features test: ${e.message} " )
239+ e.printStackTrace()
240+ }
241+ }
242+
243+ /* *
244+ * Tests migration compatibility helpers from README
245+ */
246+ fun testMigrationCompatibility () {
247+ println (" \n --- Testing Migration Compatibility ---" )
248+
249+ try {
250+ // New API - Type-safe approach (recommended)
251+ val result = JSON5 .parse(""" {"key": "value"}""" )
252+ when (result) {
253+ is JSON5Value .Object -> {
254+ val key = result.value[" key" ] as ? JSON5Value .String
255+ println (" ✓ New API result: ${key?.value} " ) // "value"
256+ }
257+ else -> println (" Result is not an object" )
258+ }
259+
260+ // Alternative: Convert to raw objects when needed
261+ fun JSON5Value.toRawObject (): Any? {
262+ return when (this ) {
263+ is JSON5Value .Null -> null
264+ is JSON5Value .Boolean -> this .value
265+ is JSON5Value .String -> this .value
266+ is JSON5Value .Number .Integer -> this .value.toDouble()
267+ is JSON5Value .Number .Decimal -> this .value
268+ is JSON5Value .Number .Hexadecimal -> this .value.toDouble()
269+ is JSON5Value .Number .PositiveInfinity -> Double .POSITIVE_INFINITY
270+ is JSON5Value .Number .NegativeInfinity -> Double .NEGATIVE_INFINITY
271+ is JSON5Value .Number .NaN -> Double .NaN
272+ is JSON5Value .Object -> this .value.mapValues { it.value.toRawObject() }
273+ is JSON5Value .Array -> this .value.map { it.toRawObject() }
274+ }
275+ }
276+
277+ // Using the helper for compatibility
278+ val rawResult = JSON5 .parse(""" {"key": "value"}""" ).toRawObject()
279+ val map = rawResult as Map <String , Any ?>
280+ println (" ✓ Compatibility helper result: ${map[" key" ]} " ) // "value"
281+
282+ } catch (e: Exception ) {
283+ println (" ⚠️ Error in migration compatibility test: ${e.message} " )
284+ e.printStackTrace()
285+ }
62286}
0 commit comments