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

在 kotlinx.serialization 中编码/解码 JSON“字符串”

如何解决在 kotlinx.serialization 中编码/解码 JSON“字符串”

是否可以在自定义序列化程序中以字符串格式对任何有效的 json 对象进行编码/解码。 例如下面的代码,但不让它序列化为 json 字符串,而是序列化为任何具有未知结构的有效 JSON?

object JsonObjectSerializer : KSerializer<JsonObject> {

    override val descriptor = PrimitiveSerialDescriptor("JsonObject",PrimitiveKind.STRING)

    override fun deserialize(decoder: Decoder): JsonObject =
        JsonObject(decoder.decodeString())

    override fun serialize(encoder: Encoder,value: JsonObject): Unit =
        encoder.encodeString(value.encode())
}

出去就像......

{
    "some": "data","jsonObject": "{\"this\": \"should not be a string\"}"
}

但是想要的输出是..

{
    "some": "data","jsonObject": {"this": "should not be a string"}
}

解决方法

encoder.encodeJsonElement 可能会做您想做的事。

我自己在 UnknownPolymorphicSerializer<P,W> 的实现中使用了 encodeJsonElement

用于 [P] 类型的多态对象的序列化程序,它将运行时未知的扩展类型包装为 [W] 类型的实例。

我提取已知结构并包装未知结构。也许一个与您所追求的用例类似的用例?具体细节和用例相当复杂,但记录在“UnknownPolymorphicSerializer: (De)serializing unknown types”中。

@InternalSerializationApi
override fun serialize( encoder: Encoder,value: P )
{
    // This serializer assumes JSON serialization with class discriminator configured for polymorphism.
    // TODO: It should also be possible to support array polymorphism,but that is not a priority now.
    if ( encoder !is JsonEncoder )
    {
        throw unsupportedException
    }
    getClassDiscriminator( encoder.json ) // Throws error in case array polymorphism is used.

    // Get the unknown JSON object.
    check( value is UnknownPolymorphicWrapper )
    val unknown = Json.parseToJsonElement( value.jsonSource ) as JsonObject

    // HACK: Modify kotlinx.serialization internals to ensure the encoder is not in polymorphic mode.
    //  Otherwise,`encoder.encodeJsonElement` encodes type information,but this is already represented in the wrapped unknown object.
    AccessInternals.setField( encoder,"writePolymorphic",false )

    // Output the originally wrapped JSON.
    encoder.encodeJsonElement( unknown )
}

附言AccessInternals 是我的预期实现,能够使用 kotlin 反射,JS 不支持,因为这是一个多平台库。

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