如何在Kotlin中使用Kotlinx Serialization编码未转义的原始JSON字符串
解决Kotlinx Serialization直接输出原始JSON字符串的问题
当使用Kotlinx Serialization作为网关服务的序列化工具时,若需要将后端返回的原始JSON字符串直接作为响应字段输出(而非转义成字符串),可以通过以下两种方案解决:
方案1:使用JsonElement替代String类型
这是最简洁直接的方案,JsonElement是Kotlinx Serialization中表示任意JSON节点的核心类型,序列化时会直接输出对应JSON结构,不会添加引号或转义字符。
修改后的完整代码:
import kotlinx.serialization.json.* import kotlinx.serialization.Serializable fun main() { // 从后端服务获取的原始JSON字符串 val backingServiceResponse = """ {"some":"json",id:123,content:[]} """.trimIndent() // 将字符串解析为JsonElement对象 val contentJson = Json.parseToJsonElement(backingServiceResponse) // 创建客户端响应对象 val packet = ExampleClientResponse("name", contentJson) val encodedPacket = Json.encodeToString(packet) println(encodedPacket) // 验证输出符合预期 require("""{"name":"name","content":{"some":"json","id":123,"content":[]}}""".trimIndent() == encodedPacket) } @Serializable data class ExampleClientResponse( val name: String, val content: JsonElement // 替换String为JsonElement类型 )
方案2:自定义序列化器(保留String字段类型)
如果因兼容性等原因必须保留content字段的String类型,可以自定义序列化器,跳过字符串的转义逻辑,直接输出原始JSON:
import kotlinx.serialization.* import kotlinx.serialization.json.* // 自定义序列化器:处理String类型的原始JSON输出 @Serializer(forClass = String::class) object RawJsonStringSerializer : KSerializer<String> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("RawJsonString", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: String) { // 将字符串解析为JsonElement后直接写入编码器 val jsonElement = Json.parseToJsonElement(value) (encoder as JsonEncoder).encodeJsonElement(jsonElement) } override fun deserialize(decoder: Decoder): String { // 反序列化时将JsonElement转回字符串 val jsonElement = (decoder as JsonDecoder).decodeJsonElement() return Json.encodeToString(jsonElement) } } @Serializable data class ExampleClientResponse( val name: String, @Serializable(with = RawJsonStringSerializer::class) // 应用自定义序列化器 val content: String ) fun main() { val backingServiceResponse = """ {"some":"json",id:123,content:[]} """.trimIndent() val packet = ExampleClientResponse("name", backingServiceResponse) val encodedPacket = Json.encodeToString(packet) println(encodedPacket) require("""{"name":"name","content":{"some":"json","id":123,"content":[]}}""".trimIndent() == encodedPacket) }
注意事项
- 确保传入的字符串是合法JSON,否则解析过程会抛出异常
- 你的Kotlin 1.8.0 + Kotlinx Serialization 1.4.1版本完全支持上述两种方案
内容的提问来源于stack exchange,提问作者aSemy
相关产品推荐
相关产品推荐

