我有一个简单的json,但包含字段具有动态对象。例如,json看起来像
{
"fixedField1": "value1",
"dynamicField1": {
"f1": "abc",
"f2": 123
}
}
或
{
"fixedField1": "value2",
"dynamicField1": {
"g1": "abc",
"g2": { "h1": "valueh1"}
}
}
我正在尝试序列化此对象,但不确定如何映射动态字段
@Serializable
data class Response(
@SerialName("fixedField1")
val fixedField: String,
@SerialName("dynamicField1")
val dynamicField: Map<String, Any> // ???? what should be the type?
)
以上代码失败,并出现以下错误
后端内部错误:代码生成期间发生异常原因: 后端(JVM)内部错误:类型为Any的元素的序列化器具有 找不到。
答案 0 :(得分:0)
当我不得不序列化任意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
定义以上方法。
在Apache 2许可下,这样的序列化器的示例在这里:ArbitraryMapSerializer.kt
然后,您可以在具有任意Map
的类上使用它。在您的示例中为:
@Serializable
data class Response(
@SerialName("fixedField1")
val fixedField: String,
@SerialName("dynamicField1")
@Serializable(with = ArbitraryMapSerializer::class)
val dynamicField: Map<String, Any>
)