Jackson在Kotlin下全局自定义序列化器Long转String不生效
起因
雪花算法生成的主键传到前段后发生精度丢失,例如后端传入1397844263642378242
,前端接收后变成1397844263642378000
因为Number的精度是16位,而雪花ID是19位
找了网上很多Java下配自定义序列化器的,改成Kotlin语法,如下
@Configuration
class JacksonConfig {
@Bean
fun jacksonObjectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {
val objectMapper: ObjectMapper = builder.createXmlMapper(false).build()
val simpleModule = SimpleModule()
.addSerializer(Long::class.java, ToStringSerializer.instance)
.addSerializer(java.lang.Long.TYPE, ToStringSerializer.instance)
objectMapper.registerModule(simpleModule)
return objectMapper
}
}
在Kotlin下怎么试都不生效,但是在字段上指定就可以
@JsonSerialize(using=ToStringSerializer.class)
val id: Long?;
解决
中文互联网找了几遍没找到,去SO一下就找到答案了
How to use springboot + kotlin + jackson to globally set a custom Long type serializer?
答主是这样解释的:The issue with your code is that the val Long
and val Long?
from Kotlin are treated differently. The first will become a long
whereas the second will become a Long
(as it can be null
).
但是这个回答提供的构造Bean的方式我不是很喜欢,因此我又找到了另一个帖子
Custom json serialization java primitives from kotlin by Jackson
最后的解决方案:
@Configuration
class JacksonConfig {
@Bean
fun jacksonObjectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {
val objectMapper: ObjectMapper = builder.createXmlMapper(false).build()
val simpleModule = SimpleModule()
.addSerializer(Long::class.javaPrimitiveType, ToStringSerializer.instance)
.addSerializer(Long::class.javaObjectType, ToStringSerializer.instance)
objectMapper.registerModule(simpleModule)
return objectMapper
}
}
相关:
val <T : Any> KClass<T>.javaPrimitiveType: Class<T>?
返回一个 JavaClass
实例,表示对应于给定KClass
的基本类型(如果存在)。
val <T : Any> KClass<T>.javaObjectType: Class<T>
返回对应于给定KClass
实例的 Java Class
实例。在原始类型的情况下,它返回相应的包装类。