当我不得不序列化任意时遇到了类似的问题Map<String, Any?>
到目前为止,我设法做到这一点的唯一方法是使用JsonObject
/ JsonElement
API 并将其与@ImplicitReflectionSerializer
主要的缺点是使用反射,它只能在 JVM 中正常工作,对于 kotlin-multiplatform 来说不是一个好的解决方案。
@ImplicitReflectionSerializer
fun Map<*, *>.toJsonObject(): JsonObject = JsonObject(map {
it.key.toString() to it.value.toJsonElement()
}.toMap())
@ImplicitReflectionSerializer
fun Any?.toJsonElement(): JsonElement = when (this) {
null -> JsonNull
is Number -> JsonPrimitive(this)
is String -> JsonPrimitive(this)
is Boolean -> JsonPrimitive(this)
is Map<*, *> -> this.toJsonObject()
is Iterable<*> -> JsonArray(this.map { it.toJsonElement() })
is Array<*> -> JsonArray(this.map { it.toJsonElement() })
else -> {
//supporting classes that declare serializers
val jsonParser = Json(JsonConfiguration.Stable)
val serializer = jsonParser.context.getContextualOrDefault(this)
jsonParser.toJson(serializer, this)
}
}
然后,要序列化,您将使用:
val response = mapOf(
"fixedField1" to "value1",
"dynamicField1" to mapOf (
"f1" to "abc",
"f2" to 123
)
)
val serialized = Json.stringify(JsonObjectSerializer, response.toJsonObject())
笔记
这种基于反射的序列化仅在您被限制使用时才需要Map<String, Any?>
如果您可以自由地使用自己的 DSL 来构建响应,那么您可以json
直接使用 DSL,这非常类似于mapOf
val response1 = json {
"fixedField1" to "value1",
"dynamicField1" to json (
"f1" to "abc",
"f2" to 123
)
}
val serialized1 = Json.stringify(JsonObjectSerializer, response1)
val response 2 = json {
"fixedField1" to "value2",
"dynamicField1" to json {
"g1" to "abc",
"g2" to json { "h1" to "valueh1"}
}
}
val serialized2 = Json.stringify(JsonObjectSerializer, response2)
但是,如果您受限于定义数据类型并进行序列化和反序列化,您可能无法使用json
DSL,因此您必须@Serializer
使用上述方法定义 a。
在 Apache 2 许可下,此类序列化程序的示例如下:ArbitraryMapSerializer.kt
Map
然后您可以在具有任意s 的类上使用它。在您的示例中,它将是:
@Serializable
data class Response(
@SerialName("fixedField1")
val fixedField: String,
@SerialName("dynamicField1")
@Serializable(with = ArbitraryMapSerializer::class)
val dynamicField: Map<String, Any>
)