首页
/ Kotlinx.serialization中自定义Double类型序列化方案详解

Kotlinx.serialization中自定义Double类型序列化方案详解

2025-06-06 09:21:10作者:傅爽业Veleda

背景介绍

在使用Kotlinx.serialization进行JSON序列化时,开发者GazimSoliev遇到了一个常见需求:希望将所有Double类型数值序列化为字符串格式而非默认的数值格式。这种需求在实际开发中很常见,特别是在需要与某些特定API交互时,或者为了避免JavaScript处理大数字时的精度问题。

问题分析

开发者最初尝试通过创建一个DoubleAsStringSerializer自定义序列化器,并在SerializersModule中注册上下文序列化器来实现这一需求。然而发现这种方式并没有按预期工作,所有Double类型仍然被序列化为数值格式。

解决方案详解

1. 使用@Contextual注解

Kotlinx.serialization要求必须显式标记哪些属性需要使用上下文序列化器。对于需要特殊处理的Double类型字段,需要在数据类中为每个相关属性添加@Contextual注解:

@Serializable
data class MyData(
    @Contextual
    val price: Double,
    @Contextual
    val amount: Double
)

2. 文件级上下文序列化

如果项目中大量使用Double类型需要特殊处理,可以使用文件级注解来简化:

@file:UseContextualSerialization(Double::class)

package com.example.myapp

@Serializable
data class MyData(
    val price: Double,  // 会自动使用上下文序列化器
    val amount: Double
)

3. 类型别名方案

更优雅的解决方案是创建类型别名并指定序列化器:

@Serializable(with = DoubleAsStringSerializer::class)
typealias StringDouble = Double

@Serializable
data class MyData(
    val price: StringDouble,  // 会使用StringDouble的序列化方式
    val amount: StringDouble
)

实现自定义序列化器

无论采用哪种方案,都需要实现自定义的Double序列化器:

internal class DoubleAsStringSerializer : KSerializer<Double> {
    override val descriptor: SerialDescriptor = 
        PrimitiveSerialDescriptor("DoubleAsString", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: Double) {
        encoder.encodeString(value.toString())
    }

    override fun deserialize(decoder: Decoder): Double {
        return decoder.decodeString().toDouble()
    }
}

配置序列化模块

在Ktor或其他框架中配置时,需要正确设置序列化模块:

install(ContentNegotiation) {
    json(Json {
        serializersModule = SerializersModule {
            contextual(Double::class, DoubleAsStringSerializer())
            // 或者如果是类型别名方案
            contextual(StringDouble::class, DoubleAsStringSerializer())
        }
    })
}

最佳实践建议

  1. 类型安全优先:推荐使用类型别名方案,它能在编译期提供更好的类型安全保证
  2. 一致性考虑:在整个项目中保持一致的序列化策略,避免混合使用不同方案
  3. 性能考量:字符串与数值之间的转换会有额外开销,在性能敏感场景需评估影响
  4. 测试验证:务必对序列化和反序列化过程进行全面测试,特别是边界值情况

通过以上方案,开发者可以灵活地控制Kotlinx.serialization中Double类型的序列化行为,满足各种特殊需求。

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

热门内容推荐

最新内容推荐

项目优选

收起
openHiTLS-examplesopenHiTLS-examples
本仓将为广大高校开发者提供开源实践和创新开发平台,收集和展示openHiTLS示例代码及创新应用,欢迎大家投稿,让全世界看到您的精巧密码实现设计,也让更多人通过您的优秀成果,理解、喜爱上密码技术。
C
52
461
kernelkernel
deepin linux kernel
C
22
5
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
349
381
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
7
0
openGauss-serveropenGauss-server
openGauss kernel ~ openGauss is an open source relational database management system
C++
131
185
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
873
517
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
336
1.09 K
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
179
264
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
607
59
note-gennote-gen
一款跨平台的 Markdown AI 笔记软件,致力于使用 AI 建立记录和写作的桥梁。
TSX
83
4