KMP中Ktor反序列化Double值变为科学计数法问题求助
Ktor 3.1.0反序列化Decimal为Double时出现科学计数法的解决办法
在KMP项目中使用Ktor 3.1.0调用RESTful服务时,接口返回的十进制数据(例如"rdInitialInventoryCost":17496887874.95)反序列化为Double类型后,会自动以科学计数法形式呈现(如1.749688787495E10),即便数据长度不长也会出现这个问题。当前使用的Ktor配置如下:
val ktorModule: Module = module { factory { HttpClient { install(ContentNegotiation) { json( Json { ignoreUnknownKeys = true prettyPrint = true isLenient = true coerceInputValues = true encodeDefaults = true allowStructuredMapKeys = true } ) } defaultRequest { url { host = ENVIRONMENT.urlSession protocol = URLProtocol.HTTPS } } install(Logging) { logger = Logger.DEFAULT level = LogLevel.ALL } install(HttpTimeout) { requestTimeoutMillis = REQUEST_TIMEOUT connectTimeoutMillis = CONNECT_TIMEOUT socketTimeoutMillis = SOCKET_TIMEOUT } } } }
解决办法
优先用BigDecimal存储高精度数值
Double是二进制浮点数,不仅容易触发科学计数法,还可能带来精度丢失问题,尤其不适合财务类高精度数值。直接把数据类里的对应字段改成BigDecimal类型,Ktor的Json序列化器原生支持这个类型的反序列化:data class InventoryData( val rdInitialInventoryCost: BigDecimal )强制Json序列化器用常规格式输出
如果必须保留Double类型,可以在Json配置里添加useScientificNumberFormat = false,强制序列化器以普通十进制格式输出数值:json( Json { ignoreUnknownKeys = true prettyPrint = true isLenient = true coerceInputValues = true encodeDefaults = true allowStructuredMapKeys = true useScientificNumberFormat = false // 新增配置 } )注意:这种方法只是改变输出格式,Double的内部存储依然是二进制浮点数,精度问题还是存在,仅适合非高精度场景。
格式化Double为字符串展示
如果只是展示时需要常规格式,可以把Double值转成格式化后的字符串。JVM端可以用DecimalFormat,跨平台场景可以用第三方格式化库:// JVM端示例 val formatter = DecimalFormat("#.##") formatter.isGroupingUsed = false val normalFormat = formatter.format(1.749688787495E10) // 得到17496887874.95
内容的提问来源于stack exchange,提问作者Juan Esteban Lopez
相关产品推荐
相关产品推荐

