You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin数据类序列化:如何用@SerialName实现类名序列化避免包装类?

问题与解决方案

问题描述

我有一个可序列化为JSON的数据类,想通过@SerialName这类注解将类名作为外层键序列化,避免使用包含File属性的包装类(会产生大量冗余类)。现有代码如下:

@Serializable
@SerialName("file")
data class File(
    val name: String,
    val version: Int,
    val type: String
)

期望生成的JSON结构为:

{ "file": { "name": "cv", "version": 1, "type": "pdf" }}

解决方案

注意:@SerialName注解的作用是指定多态序列化时的类标识或属性的JSON键名,无法直接实现给单个对象添加外层包装键的需求。以下两种方法可以避免创建包装类:

方法1:自定义序列化器

通过实现KSerializer手动控制序列化逻辑,给对象添加外层的"file"键:

@Serializable(with = FileSerializer::class)
data class File(
    val name: String,
    val version: Int,
    val type: String
)

object FileSerializer : KSerializer<File> {
    // 复用默认的序列化器
    private val delegateSerializer = File.serializer()

    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("FileWrapper") {
        // 定义外层的"file"元素,指向File的描述符
        element("file", delegateSerializer.descriptor)
    }

    override fun serialize(encoder: Encoder, value: File) {
        encoder.encodeStructure(descriptor) {
            // 将File对象序列化到"file"键下
            encodeSerializableElement(descriptor, 0, delegateSerializer, value)
        }
    }

    override fun deserialize(decoder: Decoder): File {
        return decoder.decodeStructure(descriptor) {
            // 从"file"键下反序列化出File对象
            decodeSerializableElement(descriptor, 0, delegateSerializer)
        }
    }
}

使用时直接序列化File对象即可:

val file = File("cv", 1, "pdf")
val json = Json.encodeToString(file)
// 输出结果:{"file":{"name":"cv","version":1,"type":"pdf"}}

方法2:扩展函数临时包装

通过扩展函数将File对象包装进Map,无需定义额外类,实现更简单:

// 序列化扩展函数
fun File.toWrappedJson(): String {
    val wrapper = mapOf("file" to this)
    return Json.encodeToString(wrapper)
}

// 反序列化扩展函数
fun String.toFileFromWrappedJson(): File {
    val wrapper = Json.decodeFromString<Map<String, File>>(this)
    return wrapper["file"] ?: error("JSON中缺少'file'键")
}

使用示例:

val file = File("cv", 1, "pdf")
val json = file.toWrappedJson()
val decodedFile = json.toFileFromWrappedJson()

两种方法对比

  • 自定义序列化器:符合kotlinx.serialization的规范,序列化/反序列化逻辑统一,适合需要在多处复用的场景。
  • 扩展函数:代码更简洁,实现成本低,适合临时或简单场景。

内容的提问来源于stack exchange,提问作者franks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 16:32:50