I'm trying to build a simple json parser and below is my JSON type representation with a sealed class
sealed interface JValue {
data class JString(val value: String): JValue
data class JNumber(val value: Float): JValue
data class JBool(val value: Boolean): JValue
data object JNull: JValue
data class JObject(val value: Map<String, JValue>): JValue
data class JArray(val value: List<JValue>): JValue
}
val jValueArr: JValue = getJArrayValue()
val jValueString: JValue = JValue.JString("Test")
val jValueNumber: JValue = JValue.JNumber(100f)
val jArray = JValue.JArray(listOf(jValueString, jValueNumber, jValueArr))
fun getJArrayValue(): JValue.JArray = JValue.JArray(listOf(jValueArr))
fun main() {
println(jArray.value)
}
The problematic parts are JObject and JArray as they can hold a JValue (circular dependency?)
If I run the above code it prints the below value as jArray
[JString(value=Test), JNumber(value=100.0), JArray(value=[null])]
as you see the third element is JArray(value=[null]) instead of jValueArr, but I can understand that it's null because the kotlin initializes the objects lazy and jValueArr won't be initialized while calling getJArrayValue().
My question is, how can I properly handle this scenario?
Link to my actual code - https://github.com/VenkateswaranJ/ParserCombinatorsKT/blob/master/src/main/kotlin/JsonParser.kt#L98-L130
Update:
I fixed it in my parser with some dummy forward reference (not sure it's the best way of doing it) Here is the code - https://github.com/VenkateswaranJ/ParserCombinatorsKT/blob/master/src/main/kotlin/JsonParser.kt#L16-L26
You can fix the circular initialization problem with lazy initialization of jValueArr:
unless you declare your variable lazy, it is initialized in the order of declaration.
Yet, you will still have a circular dependency issue, in your current design, your getJArrayValue function is creating a JArray with a list that contains jValueArr itself. This can lead to infinite recursion, as it's essentially a circular structure where jValueArr contains itself, which contains itself, and so on.
You should redesign your data to avoid endless recursion.