BigDecimal/Long 前后端交互失去精度解决办法
本文主要参考:https://blog.csdn.net/xu622/article/details/84326599 但是个人觉得这个博客里关于问题原因的解释有点问题。
背景
项目测试过程中,测试给我提了一个bug,新增一个BigDecimal类型数据的时候填入 1234567891234567891.12345 然后页面显示为 1234567891234568000 。
纠错
检查过程中,发现数据库保存的确实是正常的,用postman测试接口返回也是正常的。
但是发现f12调试里的数据有问题,同样的数据,在response和preview里面居然不一样
最后推测可能是json转对象时出的问题,然后用jquery的JSON.parse测了一下发现,果然是的。
最后的原因参考
解决办法
分为前端处理办法和后端处理办法
前端处理办法
tips:前端处理办法应该可以实现,但是我目前对前端技术不太通,没试过,先放着这供参考吧。
可以使用json-bigint插件来处理 https://github.com/sidorares/json-bigint
后端处理方法
1.类属性直接定义为String类型,如果需要计算的时候再转BigDecimal 。(优点:避免采坑,不必担心精度问题 缺点:可能要经常转换类型)
2.在待转换字段上加 @JsonSerialize(using = ToStringSerializer.class)
遗留问题
对BigDecima类型的属性进行转换之后发现,数据后尾会多个0,这是因为这个ToStringSerializer.class类直接对该属性进行了toString()操作。
正常来说对BigDecima类型的属性打印都是用 参考
decimalObject.stripTrailingZeros().toPlainString()
所以我们要针对BigDecima类型处理重新写一个专门的子类
public class BigDecimalToStringSerializer extends ToStringSerializer { public static final BigDecimalToStringSerializer instance = new BigDecimalToStringSerializer(); public BigDecimalToStringSerializer() { super(Object.class); } public BigDecimalToStringSerializer(Class<?> handledType) { super(handledType); } @Override public boolean isEmpty(SerializerProvider prov, Object value) { if (null == value) { return true; } String str = ((BigDecimal) value).stripTrailingZeros().toPlainString(); return str.isEmpty(); } @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(((BigDecimal) value).stripTrailingZeros().toPlainString()); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return this.createSchemaNode("string", true); } }
最后在需转换字段上加上就解决了
@JsonSerialize(using = BigDecimalToStringSerializer.class)
优化
如果需要全局加的参考