微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Kotlin:将部分 JSON 反序列化为嵌套的子对象

如何解决Kotlin:将部分 JSON 反序列化为嵌套的子对象

是否可以反序列化 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
)

我曾尝试在 JsonTransformingSerializer 上使用 Root,但是由于未找到 child 元素,这只会导致异常。

我还尝试将 child 设置为 @Transient,希望可以让我绕过这个问题,但是 JsonTransformingSerializer 仍然需要一个 KSerializer 作为其底层类作为输入,因此不起作用。

解决方法

事实证明,通过以下列方式组合 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)
        }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。