【解决方案】jison解决JS处理后台返回的Long型数据精度丢失

问题描述:

这是一个经典的js连个long类型都搞不定的问题,网上很多暴露该问题的解决方案大都是让后端把该字段改为string类型。

比如我之前也是这样做的:【问题记录】控制台解析preview和response数据不一致→解决JS处理后台返回的Long型数据精度丢失

没过多久,在网上看到了另一种稀有的处理方式——jison,号称“bison in javascript”,意思是js的一头野牛,通过它可以实现对后端返回数据的重新定义一个自己的json parser,的确野的一批啊

 

解决思路:

在拿到请求返回的数据的时候,不用json自带的那个parse方法,而是通过自己定义了一个json转换方法,然后再response给前端,这样一来前端拿到的数据就是一个动过手脚的json数据。

注:这个方法的确可以实现前端拿到的数据不出现精度丢失问题,但是再浏览器中的Preview上查看数据还是一个丢失的错误数据,这个是因为浏览器它用的还是自己原始的那个json parse方法,这个咱可以不管它的,除非去再整个浏览器插件改变浏览器的json parse方法?

 

效果展示:

为方便测试,我们在ctime这个字段存了一个会出现精度丢失的Long数据(11111111111111111

在Response窗口中,我们可以看到这里拿到的数据还是正常的,这也给我们提供了可实现的机会,不然连拿到的数据都是错的,那就真的是无可奈何了。

点开Preview窗口,我们可以看到这里显示的就是精度已丢失后的惨痛结果。

但是,我通过控制台输出我前端真实拿到手的数据......嘿嘿嘿......劳资成功了!

除了ctime 一切Long类型的到前端手里都会转为string以确保数据正常,比照截图两张如下:

 

解决方案:

了解一下网上那些个不清不楚的介绍文档吧,总归还是很感谢他们的分享,为我们提供了解决思路与方案。

jison源码:https://github.com/zaach/jison

jsonlint源码:https://github.com/zaach/jsonlint

最感谢的资源文章:js处理Json中的长整数

同样的知乎问题:javascript 精度问题导致后端传过来的值显示不正确,有何好的解决办法?

通读以上资源之后,最终得出的结论就是:

第一步,安装野牛大哥 -- jison

npm install jison

第二步,搞两个文件,并修改其中一个文件关于Number类型转换的逻辑

先去这里把 jsonlint.l、jsonlint.y 下载到本地项目中,如图:

这两个文件分别是 词表文件 - lexfile - jsonlint.l、语法文件 - grammFile - jsonlint.y

修改 jsonlint.y 词法文件关于JSONNumber的这段代码:

JSONNumber
    : NUMBER
        {$$ = yytext == String(Number(yytext))? Number(yytext): yytext;}
    ;

第三步,生成我们要的 jsonlint.js

用第一步的野牛大哥把第二步的两位文件合成一个我们要的最终插件,在控制台输入:

jison jsonlint.y jsonlint.l

编译完成之后,我们的目录下就诞生我们要的这个js了,如图:

第四步,引入 jsonlint.js 至项目

截止目前,如果您想省去以上三步,直接搞到修改后生产的 jsonlint.js 文件,可以点击下方链接直接下载:

自定义生成后的jsonlint

正确的服用方式:

这是基于jison工具,通过修改JSONNumber中的numer转换规则,将long类型的numer值进行匹配,然后将其转为string,从而避免Long类型的数据在js中出现精度丢失的问题。 该jsonling.js文件是已经修改过后生产的辅助文件,可直接在项目中引用。 使用方法: 1、在html中引入该文件 <script src="./static/jsonlint.js"></script> 2、在请求的相应数据response中调用它 return jsonlint.parse(data) 3、可在控制台查看每次请求拿到的数据,long类型已转换string; 注意浏览器中的Preview显示还是异常的,这个不影响前端读取数据。

将我们好不容易生产出来的 jsonlint.js 放到 static 目录下,方便项目引用。

在 index.html 中:

<script src="./static/jsonlint.js"></script>

第五步,用它

在我们请求的返回数据中,做一层拦截转换,此处以 axios 的实现方法为例:

// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
    /* eslint-disable no-undef */
    return jsonlint.parse(data)
}]

 

 

完。

 

 

相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页