首页
/ Kotlinx.Serialization实战:自定义时间戳的JSON原始类型序列化

Kotlinx.Serialization实战:自定义时间戳的JSON原始类型序列化

2025-06-07 15:51:03作者:羿妍玫Ivan

在Kotlin生态中,kotlinx.serialization作为官方推荐的序列化库,其灵活的自定义序列化能力常被开发者使用。本文将通过一个典型场景——将自定义时间戳对象序列化为JSON原始数值类型(而非默认的对象结构),深入解析其实现原理。

场景需求

假设我们有一个Timestamp类型,其内部存储的是UNIX纪元起的微秒数(即毫秒值×1000)。服务端接口要求该类型必须以原始数值形式传输,而非JSON对象结构。

常见误区

许多开发者会直接使用@Serializer注解生成默认序列化器,如下所示:

@Serializer(forClass = Timestamp::class)
object TimestampSerializer : KSerializer<Timestamp> {
    override fun deserialize(decoder: Decoder) {
        decoder.decodeStructure(descriptor) {
            Timestamp(decodeLongElement(descriptor, 0) / 1000)
        }
    }
    // 省略serialize实现...
}

这种实现会强制将时间戳处理为JSON对象结构(如{"element":1634567890000}),而我们需要的是直接输出数值(如1634567890000)。

核心解决方案

关键在于正确配置serialDescriptor。序列化描述符决定了数据在序列化流中的结构形态。对于原始数值类型,我们需要使用PrimitiveSerialDescriptor

@Serializer(forClass = Timestamp::class)
object TimestampSerializer : KSerializer<Timestamp> {
    // 关键点:声明为LONG型原始描述符
    override val descriptor = PrimitiveSerialDescriptor(
        "com.example.Timestamp", 
        PrimitiveKind.LONG
    )

    override fun deserialize(decoder: Decoder): Timestamp {
        // 直接解码为原始long值
        return Timestamp(decoder.decodeLong() / 1000)
    }

    override fun serialize(encoder: Encoder, value: Timestamp) {
        // 直接编码为原始long值
        encoder.encodeLong(value.toInstant().toEpochMilli() * 1000L)
    }
}

技术原理深度解析

  1. 描述符类型决定序列化形态

    • StructureDescriptor对应JSON对象
    • PrimitiveSerialDescriptor对应JSON原始值(数值/字符串/布尔值)
  2. 微秒与毫秒转换: 示例中/1000*1000L的转换处理,体现了时间单位转换的常见模式。实际业务中需根据具体协议调整。

  3. IDE静态检测的局限性: 当前Kotlin插件无法验证序列化实现与描述符的匹配性,开发者需自行保证:

    • 使用PrimitiveSerialDescriptor时,必须调用decodeXXX()原始方法
    • 不能使用decodeStructure等结构化方法

最佳实践建议

  1. 单元测试验证
@Test
fun testTimestampSerialization() {
    val json = Json.encodeToString(TimestampSerializer, timestamp)
    assertTrue(json.toLongOrNull() != null) // 验证输出是原始数值
}
  1. 考虑跨平台一致性: 如果涉及多平台项目,建议将序列化逻辑放在commonMain模块中。

  2. 性能优化: 对于高频调用的时间戳序列化,可将serializer对象声明为单例(如示例中的object)。

通过本文的解决方案,开发者可以优雅地实现自定义类型到JSON原始值的映射,满足各类严苛的接口协议要求。

登录后查看全文
热门项目推荐
相关项目推荐