This discussion has been going on a long time and is quite lengthy so my use case may already be well represented, especially by JSON-specific use cases.
I’m writing an application that consumes an XML-RPC API, and the XML-RPC spec prescribes a set of allowable types similar to JSON: int
, string
, double
, boolean
, array
, struct
, and null
.
Right now I have these represented as a pile of sealed types that looks more-or-less like this (left out @Serializable
and @JvmInline
annotations where applicable for the sake of brevity):
sealed interface ValueType
sealed interface PrimitiveType : ValueType
sealed interface CompositeType : ValueType
value class StringType(val value: String) : PrimitiveType
value class IntType(val value: Int) : PrimitiveType
value class BooleanType private constructor(val value: Int) : PrimitiveType
value class DoubleType(val value: Double) : PrimitiveType
object NullType : PrimitiveType
data class ArrayType(val data: List<ValueType>) : CompositeType
data class StructType(val members: Map<String, ValueType>) : CompositeType
Right now I’m trying to add an extra layer on top of StructType
to help unboxing members
so application code can work directly with builtin types instead of ValueType
. Unfortunately the API so far is very boilerplate-y with a set of functions like:
fun StructType.intOrNull(key: String): Int? {
require(key in members) { "No member named $key" }
return members[key]
}
fun StructType.doubleOrNull(key: String): Double? ...
fun StructType.booleanOrNull(key: String): Boolean? ...
fun StructType.stringOrNull(key: String): String? ...
where each on is identitcal except the return type.
If instead I was able to do something like this (which I think is some combination of many other suggestions in this thread):
typealias XmlRpcValue = Int? | Double? | Boolean? | String? | List<ValueType>? | Map<String, ValueType>?
it would not only make my “unboxing” API easier, but also (probably) allow me to drop my pile of sealed types all together and work directly with builtin types.