Kotlin:将 JSON 的部分反序列化为嵌套的子对象
Kotlin: Deserialize parts of JSON into nested child objects
是否可以反序列化 JSON 结构,以便将该结构的部分收集到嵌套的子对象中?
所以给出这个 JSON 结构
{
"root_field1": "This field will be in root",
"root_field2": "This field will be in root",
"child_field1": "This field will be in a child object",
"child_field2": 123
}
是否可以使用 JSONTransformSerializer
(或其他方式)将上述 json 反序列化为:
@Serializable
data class Root(
@SerialName("root_field1")
val field1: String,
@SerialName("root_field2")
val field2: String,
val child: Child
)
@Serializable
data class Child(
@SerialName("child_field1")
val field1: String,
@SerialName("child_field2")
val field2: Int
)
我试图在 Root
上使用 JsonTransformingSerializer
,但是由于未找到 child
元素,这只会导致异常。
我还尝试将 child
设置为 @Transient
希望可以绕过这个问题,但是 JsonTransformingSerializer
仍然需要 KSerializer
底层 class 作为输入,因此不起作用。
事实证明,通过按以下方式组合 JsonTransformingSerializer<Root>
和自定义 KSerializer<Root>
(我之前没想过)这很容易实现:
object RootTransformingSerializer : JsonTransformingSerializer<Root>(RootSerializer()) {
private val childSet: Set<String> = setOf("child_field1", "child_field2")
override fun transformDeserialize(element: JsonElement): JsonElement {
val child = MutableMap<String, JsonElement> = mutableMapOf()
return buildJsonObject(){
element.forEach { entry ->
if (entry.key in childSet) {
child.put(entry.key, entry.value)
} else {
put(entry.key, entry.value)
}
}
put("child", JsonObject(child))
}
}
}
自定义 KSerializer 如下所示
object RootSerializer : KSerializer<Root> {
override val descriptor: SerialDescriptor
get() = buildClassSerialDescriptor("Root") {
element<String>("root_field1")
element<String>("root_field2")
element<Child>("child")
}
override fun deserialize(decoder: Decoder): Commit {
return decoder.decodeStructure(descriptor) {
val rootField1 = decodeStringElement(descriptor, 0)
val rootField2 = decodeStringElement(descriptor, 1)
val child = decodeSerializableElement(descriptor, 2, Child.serializer())
Root(rootField1, rootField2, child)
}
}
是否可以反序列化 JSON 结构,以便将该结构的部分收集到嵌套的子对象中?
所以给出这个 JSON 结构
{
"root_field1": "This field will be in root",
"root_field2": "This field will be in root",
"child_field1": "This field will be in a child object",
"child_field2": 123
}
是否可以使用 JSONTransformSerializer
(或其他方式)将上述 json 反序列化为:
@Serializable
data class Root(
@SerialName("root_field1")
val field1: String,
@SerialName("root_field2")
val field2: String,
val child: Child
)
@Serializable
data class Child(
@SerialName("child_field1")
val field1: String,
@SerialName("child_field2")
val field2: Int
)
我试图在 Root
上使用 JsonTransformingSerializer
,但是由于未找到 child
元素,这只会导致异常。
我还尝试将 child
设置为 @Transient
希望可以绕过这个问题,但是 JsonTransformingSerializer
仍然需要 KSerializer
底层 class 作为输入,因此不起作用。
事实证明,通过按以下方式组合 JsonTransformingSerializer<Root>
和自定义 KSerializer<Root>
(我之前没想过)这很容易实现:
object RootTransformingSerializer : JsonTransformingSerializer<Root>(RootSerializer()) {
private val childSet: Set<String> = setOf("child_field1", "child_field2")
override fun transformDeserialize(element: JsonElement): JsonElement {
val child = MutableMap<String, JsonElement> = mutableMapOf()
return buildJsonObject(){
element.forEach { entry ->
if (entry.key in childSet) {
child.put(entry.key, entry.value)
} else {
put(entry.key, entry.value)
}
}
put("child", JsonObject(child))
}
}
}
自定义 KSerializer 如下所示
object RootSerializer : KSerializer<Root> {
override val descriptor: SerialDescriptor
get() = buildClassSerialDescriptor("Root") {
element<String>("root_field1")
element<String>("root_field2")
element<Child>("child")
}
override fun deserialize(decoder: Decoder): Commit {
return decoder.decodeStructure(descriptor) {
val rootField1 = decodeStringElement(descriptor, 0)
val rootField2 = decodeStringElement(descriptor, 1)
val child = decodeSerializableElement(descriptor, 2, Child.serializer())
Root(rootField1, rootField2, child)
}
}