如何在JSON中保留BigDecimal末尾零?自定义序列化器丢失末尾零
如何让BigDecimal序列化时保留两位小数及末尾的零
嘿,我注意到你已经实现了PriceJsonSerializer来限制BigDecimal到小数点后两位,但现在遇到了末尾零被自动移除的问题——比如95.50会被序列化成95.5。这其实是因为BigDecimal的toString()方法会自动省略无意义的末尾零,咱们可以通过调整序列化逻辑来解决这个需求。
问题根源
你当前的代码里,value.setScale(2, BigDecimal.ROUND_HALF_UP).toString()这一步,toString()会把格式化后的BigDecimal转换成最简洁的字符串形式,所以95.50就变成了95.5。如果想要强制保留两位小数,得换一种格式化方式。
改进后的序列化器代码
我们可以用DecimalFormat来指定固定的小数位数格式,确保末尾的零不会被省略:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; public class PriceJsonSerializer extends JsonSerializer<BigDecimal> { // 定义强制保留两位小数的格式,确保末尾零不丢失 private static final DecimalFormat DECIMAL_FORMAT; static { // 避免受系统区域影响,指定用英文小数点 DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH); DECIMAL_FORMAT = new DecimalFormat("#.00", symbols); // 设置四舍五入规则,和你原来的逻辑保持一致 DECIMAL_FORMAT.setRoundingMode(java.math.RoundingMode.HALF_UP); } @Override public void serialize(BigDecimal value, JsonGenerator jgen, SerializerProvider provider) throws IOException { // 直接用DecimalFormat格式化,既做了四舍五入又保证了两位小数 String formattedPrice = DECIMAL_FORMAT.format(value); jgen.writeString(formattedPrice); } }
重要说明
- 为什么用
writeString()?:如果用writeNumber(),JSON的数字类型本身是不区分95.5和95.50的——它们的数值完全相等,所以即使你写入"95.50"作为数字,解析器还是会把它当成95.5处理。如果业务要求JSON里必须显示两位小数(包括末尾零),只能把它序列化成字符串类型。 - 区域设置的作用:添加
DecimalFormatSymbols是为了避免某些地区用逗号作为小数点分隔符,确保输出的格式是标准的小数点形式。 - 如果必须是数字类型:如果你的业务要求JSON中必须是数字,那其实没办法在JSON层面保留末尾的零,因为这是JSON数字类型的特性。这种情况下,建议后端只保证数值精度(保留两位小数),前端在展示的时候再做格式化处理,比如用
toFixed(2)方法。
内容的提问来源于stack exchange,提问作者user2160534
相关产品推荐
相关产品推荐

