所有分类
  • 所有分类
  • 未分类

SpringBoot-解决BigDecimal传到前端后精度丢失的问题

简介

本文用示例介绍SpringBoot如何解决BigDecimal传到前端后精度丢失问题。

问题复现

前后端交互没问题

Controller

package com.knife.example.business.product.controller;

import com.knife.example.business.product.vo.ProductVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@Api(tags = "商品")
@RestController
@RequestMapping("product")
public class ProductController {

    @ApiOperation("查询")
    @GetMapping("query")
    public ProductVO query(BigDecimal amount) {

        //省略查数据库等逻辑。
        //为了简便,直接虚构一个vo
        ProductVO productVO = new ProductVO();
        productVO.setId(2L);
        productVO.setName("鼠标");
        productVO.setAmount(amount);

        return productVO;
    }
}

Entity

package com.knife.example.business.product.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;

@Data
@ApiModel("商品响应类")
public class ProductVO {
    @ApiModelProperty("id")
    private Long id;

    @ApiModelProperty("名字")
    private String name;

    @ApiModelProperty("金额")
    private BigDecimal amount;
}

测试

访问:http://localhost:8080/product/query?amount=12345671234567.1234

结果

看上去没有问题,但是,前端会对数字进行处理,详见下方

前端处理数字会有问题

场景描述

实际项目中前端会这样处理:调用后端接口获得JSON格式的响应字符串,然后将JSON字符串解析为JavaScript对象(用于展示到对应的位置、方便计算等)。

前端调后端的写接口(增删改)时,会将JavaScript对象序列化为JSON格式的字符串,然后将其作为参数请求后端接口。

 实例1:精度丢失

const json = '{"id": 1, "name": "鼠标", "amount": 12345671234567.12345}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 12345671234567.123
console.log(JSON.stringify(obj));  // {"id":1,"name":"鼠标","amount":12345671234567.123}

可以看到,在将json字符串转为JavaScript对象后,“amount” 丢失了精度。

实例2:丢失小数位

const json = '{"id": 1, "name": "鼠标", "amount": 12345671234567.00000}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 12345671234567
console.log(JSON.stringify(obj));  // {"id":1,"name":"鼠标","amount":12345671234567}

可以看到,在将json字符串转为JavaScript对象后,“amount” 丢失了小数。

其他示例

const json = '{"id": 1, "name": "鼠标", "amount": 12345671234567.12345}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 12345671234567.123

const json = '{"id": 1, "name": "鼠标", "amount": 123456712345678.12345}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 123456712345678.12

const json = '{"id": 1, "name": "鼠标", "amount": 98765432198765.12345}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 98765432198765.12

const json = '{"id": 1, "name": "鼠标", "amount": 987654321987654321.12345}';
const obj = JSON.parse(json);
console.log(obj.amount);  // 987654321987654300

Java后端BigDecimal的范围

  1. 范围没有限制,可以认为无限大、无限小
  2. 可以通过如下代码验证:
package com.example.a;
 
import java.math.BigDecimal;
 
public class Demo {
    public static void main(String[] args) {
        BigDecimal bigDecimal = new BigDecimal(
                "1234567890123456789012345678901234567890"
                        + "1234567890123456789012345678901234567890"
                        + ".123456789"
        );
        System.out.println(bigDecimal);
    }
}

执行结果:

12345678901234567890123456789012345678901234567890123456789012345678901234567890.123456789

解决方案

此内容仅限VIP查看,请先
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录