使用kotlinx.serialization编码/解码JSON“字符串”

4

是否可能使用自定义序列化器将任何有效的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())
}

Out would be something like..

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

但是期望的输出结果应该是。。。

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

你有找到任何解决方案吗?Jackson似乎提供了这个功能(至少在序列化方面),通过@JsonRawValue注释,但我似乎在kotlinx.serialization中找不到相同的功能。 - Michele Palmia
@MichelePalmia 是的,可以使用JsonElement作为可序列化值 https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#json-elements - Chris
1个回答

1

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。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接