Nir
07/15/2020, 9:08 PMclass JsonValue {
constructor()
sealed class JsonData {
class IntWrapper(val x: Int) : JsonData()
class StringWrapper(val x: String) : JsonData()
class ListWrapper(val x: MutableList<JsonValue>) : JsonData()
class ObjectWrapper(val x: MutableMap<String, JsonValue>) : JsonData()
class NullWrapper() : JsonData()
}
var jsonData: JsonData = JsonData.NullWrapper()
companion object {
fun make(x: Int): JsonValue {
val j = JsonValue()
j.jsonData = JsonData.IntWrapper(x)
return j
}
fun make(x: String): JsonValue {
val j = JsonValue()
j.jsonData = JsonData.StringWrapper(x)
return j
}
inline fun <reified T> make(x: List<T>): JsonValue {
val j = JsonValue()
j.jsonData = JsonData.ListWrapper(x.map { JsonValue.make(it) })
return j
}
}
}
So, json is basically a recursive sum type. Sum types in kotlin are typically done via sealed classes, so I'm doing my best with those. I'm trying to have a generic factory function here that works recursively. The problem is, my generic make
that takes a List complains, because the T is not constrained. However, I can only constrain types in Kotlin by interfaces/classes, and I can't add add any new bases/interfaces to types like Int and String, that I want this to work with conveniently. So, is there any nice way to work around this? Or should I basically declare defeat, change the signature to fun make(x: List<JsonValue>)
and put the onus on the user to convert e.g. a List<int>
into a List<JsonValue>
?Nir
07/15/2020, 9:12 PMNir
07/15/2020, 9:12 PMNir
07/15/2020, 9:12 PMNir
07/15/2020, 9:13 PMmake
like thisNir
07/15/2020, 9:13 PMinline fun <reified T> make(x: List<T>): JsonValue {
val j = JsonValue()
if (T::class == Int::class) {
j.jsonData = JsonData.ListWrapper(x.map { JsonValue.make(it as Int) }.toMutableList())
}
if (T::class == String::class) {
j.jsonData = JsonData.ListWrapper(x.map { JsonValue.make(it as String) }.toMutableList())
}
if (T::class == List::class) {
j.jsonData = JsonData.ListWrapper(x.map { JsonValue.make(it as List<>) }.toMutableList())
}
return j
}
Nir
07/15/2020, 9:13 PMNir
07/15/2020, 9:14 PMNir
07/15/2020, 9:15 PMaraqnid
07/15/2020, 10:29 PMmake(Any)
function that would use the run-time type to return a JsonValueDico
07/15/2020, 11:56 PMNir
07/16/2020, 1:55 PMNir
07/16/2020, 1:56 PMNir
07/16/2020, 1:57 PMNir
07/16/2020, 1:58 PMNir
07/16/2020, 1:59 PMNir
07/16/2020, 3:53 PMNir
07/16/2020, 3:53 PMNir
07/16/2020, 3:54 PMNir
07/16/2020, 3:55 PMDico
07/17/2020, 1:00 AMAny
that calls the corresponding one, might be decent.Nir
07/17/2020, 2:23 PMNir
07/17/2020, 2:24 PMx: List<Map<String, List<Int>>>
, without a recursive function that works correctly, the user is going to have to do the conversions themselves, at every levelNir
07/17/2020, 2:27 PMj = x.map { JsonValue( it.mapValues { JsonValue ( it.map { JsonValue(it) } ) } ) }
Nir
07/17/2020, 2:27 PM