如何使用Jackson XMLMapper实现浮点类型十进制分隔符的本地化
解决方案
Jackson本身没有内置十进制分隔符本地化的开关,但可以通过自定义数值序列化器+全局注册的方式优雅实现,属于Jackson标准扩展能力,不需要修改核心逻辑。
实现步骤
- 自定义浮点/十进制类型序列化器
这里我们统一处理Float/Double/BigDecimal三类数值类型,可按需调整小数保留位数:
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.ser.std.StdSerializer import java.text.DecimalFormat import java.text.DecimalFormatSymbols // 通用本地化数值序列化器 class LocalizedNumberSerializer(t: Class<*>) : StdSerializer<Number>(t) { // 配置格式:保留2位小数,十进制分隔符为逗号 private val format = DecimalFormat("0.00").apply { decimalFormatSymbols = DecimalFormatSymbols().apply { decimalSeparator = ',' } isGroupingUsed = false // 关闭千位分隔符,如有需要可自行开启 } override fun serialize(value: Number, gen: JsonGenerator, provider: SerializerProvider) { gen.writeString(format.format(value)) } }
注意:XML Schema的原生数值类型要求用
.作为十进制分隔符,逗号分隔符的数值本身不符合XML数值标准,因此序列化后以字符串类型承载该值,是该场景下的通用实现方式。
- 将序列化器注册到XmlMapper
创建SimpleModule注册自定义序列化器,添加到原有配置中即可全局生效:
import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.dataformat.xml.XmlMapper import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator val xmlMapper = XmlMapper() // 新增:注册本地化数值序列化器 val numberModule = SimpleModule() numberModule.addSerializer(Float::class.java, LocalizedNumberSerializer(Float::class.java)) numberModule.addSerializer(Double::class.java, LocalizedNumberSerializer(Double::class.java)) numberModule.addSerializer(BigDecimal::class.java, LocalizedNumberSerializer(BigDecimal::class.java)) xmlMapper.registerModule(numberModule) // 保留原有配置不变 xmlMapper.enable(SerializationFeature.INDENT_OUTPUT) xmlMapper.propertyNamingStrategy = CustomPropertyNamingStrategy() xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true) xmlMapper.setDefaultUseWrapper(false)
可选扩展
如果不需要全局生效,仅需要部分字段使用逗号分隔符,可以去掉全局注册的逻辑,直接在对应字段上添加@JsonSerialize注解即可:
data class YourXmlEntity( @JacksonXmlProperty(localName = "amount") @JsonSerialize(using = LocalizedNumberSerializer::class) val amount: Double )
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

