-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Right now JSON5 only has following usable API that returns Any?
fun parse(text: String): Any? {
return JSON5Parser.parse(text)
}However, it would be ideal to provide a sealed class with allowed classes based on JSON5 specification as seen in https://spec.json5.org/
Here is an idea of sealed class that would represent possible values. However, double check the JSON specification so that it closely resembles the spec and add kdoc with URL link for easy reference to original spec.
package dev.hossain.json5kt.model
/**
* Represents a JSON5 value as described in the specification.
* JSON5 values can be objects, arrays, strings, numbers, booleans, or null.
*/
sealed class JSON5Value {
/**
* Represents a JSON5 object, which is a collection of name/value pairs.
*
* @property value The map of property names to JSON5 values
*/
data class Object(val value: Map<String, JSON5Value>) : JSON5Value() {
override fun toString(): String = value.toString()
}
/**
* Represents a JSON5 array, which is an ordered sequence of JSON5 values.
*
* @property value The list of JSON5 values
*/
data class Array(val value: List<JSON5Value>) : JSON5Value() {
override fun toString(): String = value.toString()
}
/**
* Represents a JSON5 string value.
*
* @property value The string value
*/
data class String(val value: kotlin.String) : JSON5Value() {
override fun toString(): kotlin.String = "\"$value\""
}
/**
* Represents a JSON5 number value, which can be an integer, float, hex, infinity, or NaN.
*/
sealed class Number : JSON5Value() {
/**
* Represents an integer number in JSON5.
*
* @property value The integer value
*/
data class Integer(val value: Long) : Number() {
override fun toString(): kotlin.String = value.toString()
}
/**
* Represents a decimal number in JSON5.
*
* @property value The decimal value
*/
data class Decimal(val value: Double) : Number() {
override fun toString(): kotlin.String = value.toString()
}
/**
* Represents a hexadecimal number in JSON5 (0x prefix).
*
* @property value The integer value represented by the hex
*/
data class Hexadecimal(val value: Long) : Number() {
override fun toString(): kotlin.String = "0x${value.toString(16)}"
}
/**
* Represents positive infinity in JSON5.
*/
object PositiveInfinity : Number() {
override fun toString(): kotlin.String = "Infinity"
}
/**
* Represents negative infinity in JSON5.
*/
object NegativeInfinity : Number() {
override fun toString(): kotlin.String = "-Infinity"
}
/**
* Represents NaN (Not a Number) in JSON5.
*/
object NaN : Number() {
override fun toString(): kotlin.String = "NaN"
}
}
/**
* Represents a JSON5 boolean value.
*
* @property value The boolean value
*/
data class Boolean(val value: kotlin.Boolean) : JSON5Value() {
override fun toString(): kotlin.String = value.toString()
}
/**
* Represents a JSON5 null value.
*/
object Null : JSON5Value() {
override fun toString(): kotlin.String = "null"
}
/**
* Helper method to convert primitive Kotlin types to JSON5Value objects.
*/
companion object {
/**
* Creates a JSON5Value from a Kotlin object.
*
* @param value The Kotlin object to convert
* @return The corresponding JSON5Value
*/
fun from(value: Any?): JSON5Value {
return when (value) {
null -> Null
is Map<*, *> -> {
val jsonMap = mutableMapOf<kotlin.String, JSON5Value>()
value.forEach { (k, v) ->
if (k is kotlin.String) {
jsonMap[k] = from(v)
}
}
Object(jsonMap)
}
is List<*> -> {
val jsonList = value.map { from(it) }
Array(jsonList)
}
is kotlin.String -> String(value)
is Int -> Number.Integer(value.toLong())
is Long -> Number.Integer(value)
is Float -> Number.Decimal(value.toDouble())
is Double -> {
when {
value.isNaN() -> Number.NaN
value.isInfinite() && value > 0 -> Number.PositiveInfinity
value.isInfinite() && value < 0 -> Number.NegativeInfinity
else -> Number.Decimal(value)
}
}
is kotlin.Boolean -> Boolean(value)
else -> throw IllegalArgumentException("Unsupported type: ${value::class.java}")
}
}
}
}And the updated API would be something like this
/**
* Parses a JSON5 string into a strongly-typed JSON5Value.
*
* @param text JSON5 text to parse
* @return The parsed value as a JSON5Value
* @throws JSON5Exception if the input is invalid JSON5
*/
fun parse(text: String): JSON5Value {
val result = JSON5Parser.parse(text)
return JSON5Value.from(result)
}Keep the original function like this, so that it can be used for generic purpose:
/**
* Parses a JSON5 string into a raw Kotlin object without type conversion.
*
* @param text JSON5 text to parse
* @return The parsed value (Map, List, String, Number, Boolean, or null)
* @throws JSON5Exception if the input is invalid JSON5
*/
fun parseToAny(text: String): Any? {
return JSON5Parser.parse(text)
}Update API and model classed and unit tests according to API changes and updates. Validate all tests passes after API changes.
Copilot
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request