Dariusz Kuc
02/15/2021, 6:44 PM@Serializable
data class GraphQLResponse<T>(
val data: T? = null,
val errors: List<GraphQLError>? = null,
val extensions: Map<Any, Any>? = null // complains about missing serializer for Any
)
araqnid
02/15/2021, 8:08 PMaraqnid
02/15/2021, 8:08 PMDariusz Kuc
02/15/2021, 8:17 PMJsonElement
to users seems like leaking internals vs just giving them the mapDariusz Kuc
02/15/2021, 8:18 PMDariusz Kuc
02/15/2021, 9:26 PM@Serializable
data class GraphQLResponse<T>(
val data: T? = null,
// val errors: List<GraphQLError>? = null,
@Serializable(with = GenericMapSerializer::class)
val extensions: Map<Any, Any>? = null // complains about missing Any serializer
)
object GenericMapSerializer : KSerializer<Map<Any, Any>> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("GenericMap")
override fun serialize(encoder: Encoder, value: Map<Any, Any>) {
val jsonEncoder = encoder as JsonEncoder
val jsonMap = value.entries.associate { entry ->
entry.key.toString() to serializeAny(entry.value)
}
jsonEncoder.encodeJsonElement(JsonObject(jsonMap))
}
private fun serializeAny(value: Any?): JsonElement = when (value) {
is Map<*, *> -> {
val mapContents = value.entries.associate { mapEntry ->
mapEntry.key.toString() to serializeAny(mapEntry.value)
}
JsonObject(mapContents)
}
is List<*> -> {
val arrayContents = value.map { listEntry -> serializeAny(listEntry) }
JsonArray(arrayContents)
}
is Number -> JsonPrimitive(value)
is Boolean -> JsonPrimitive(value)
else -> JsonPrimitive(value.toString())
}
override fun deserialize(decoder: Decoder): Map<Any, Any> {
val jsonDecoder = decoder as JsonDecoder
val element = jsonDecoder.decodeJsonElement()
return if (element is JsonObject) {
element.mapValues { deserializeJsonElement(it.value) }
} else {
throw SerializationException("cannot deserialize to a map as specified field is not an object")
}
}
private fun deserializeJsonElement(element: JsonElement): Any = when (element) {
is JsonObject -> {
element.mapValues { deserializeJsonElement(it.value) }
}
is JsonArray -> {
element.map { deserializeJsonElement(it) }
}
is JsonPrimitive -> element.toString()
}
}
Dariusz Kuc
02/16/2021, 2:55 AMAny
and not on a map, i.e.
@Serializable
data class GraphQLResponse<T>(
val data: T? = null,
// val errors: List<GraphQLError>? = null,
val extensions: Map<String, @Serializable(with = AnySerializer::class) Any>? = null
)
object AnySerializer : KSerializer<Any> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Any")
override fun serialize(encoder: Encoder, value: Any) {
val jsonEncoder = encoder as JsonEncoder
val jsonElement = serializeAny(value)
jsonEncoder.encodeJsonElement(jsonElement)
}
private fun serializeAny(value: Any?): JsonElement = when (value) {
is Map<*, *> -> {
val mapContents = value.entries.associate { mapEntry ->
mapEntry.key.toString() to serializeAny(mapEntry.value)
}
JsonObject(mapContents)
}
is List<*> -> {
val arrayContents = value.map { listEntry -> serializeAny(listEntry) }
JsonArray(arrayContents)
}
is Number -> JsonPrimitive(value)
is Boolean -> JsonPrimitive(value)
else -> JsonPrimitive(value.toString())
}
override fun deserialize(decoder: Decoder): Any {
val jsonDecoder = decoder as JsonDecoder
val element = jsonDecoder.decodeJsonElement()
return deserializeJsonElement(element)
}
private fun deserializeJsonElement(element: JsonElement): Any = when (element) {
is JsonObject -> {
element.mapValues { deserializeJsonElement(it.value) }
}
is JsonArray -> {
element.map { deserializeJsonElement(it) }
}
is JsonPrimitive -> element.toString()
}
}