Jison解决JS处理后端返回的Long型数据精度丢失问题
栏目: JavaScript · 发布时间: 5年前
内容简介:在前端页面展示数据的时候,通常都需要处理来自后端的json数据。通常这个过程都是非常简单的,比如通过jQuery的ajax。但是如果服务器传来的json中包含一个很大的整数,如 { "id": 296675198462066688 } ,那么接受后会发现变成了 { id: 296675198462066700 } 。js是弱类型语言,所有的数字类型统称为Number类型,不区分int、long、double等。而Number是根据IEEE 754标准中的double来实现的,即所有的Number类型都是64
在前端页面展示数据的时候,通常都需要处理来自后端的json数据。通常这个过程都是非常简单的,比如通过jQuery的ajax。但是如果服务器传来的json中包含一个很大的整数,如 { "id": 296675198462066688 } ,那么接受后会发现变成了 { id: 296675198462066700 } 。
简单的解决方法,让后端传给你string类型 但是后端的人会说:你们前端怎么显示个long类型都搞不定! 复制代码
问题原因
js是弱类型语言,所有的数字类型统称为Number类型,不区分int、long、double等。而Number是根据IEEE 754标准中的double来实现的,即所有的Number类型都是64位双精度实型。segmentfault上提供了一个对IEEE 574标准 非常友好的讲解,这里不再讲述。
js内置有32位整数,而number类型的安全整数是53位。如果超过53位的,你不能用json传递,需要用其他数据类型,比如字符串,或拆分成两个数据字段。
解决思路
GitHub开源项目—— Jison ,号称“bison in javascript”,通过它可以实现对后端返回数据的重新定义一个自己的json parser。
在拿到接口请求返回的数据的时候,不用json自带的那个parse方法,而是通过自己定义了一个json转换方法,然后再response给前端,这样一来前端拿到的数据就是一个处理过的json数据。
自定义 json parser
首先使用Node安装Jison
npm install jison -g 复制代码
同时在 lib 目录下提供了 cli.js 来生成我们想自定义的parser。参数有两个(详见cli.js代码), cli.js grammaFile lexFile ,grammaFile是语法文件,lexFile是词表文件。
下面就是怎么写这两个文件了,可以通过文档 来学习一下这类文件的语法。如果不想这么麻烦,还可以在jison作者的另一个项目—— jsonlint 里面找到,在github中该项目的src目录下提供了jsonlint.y(grammaFile)和jsonlint.l(lexFile)两个文件。使用这两个文件可以直接生成jsonlint.js,放到网页中当json parser来使用。
这里我们以修改jsonlint里面的两个文件为例生成我们所需要的json parse
我们的目的是让一些会丢失精度的整数被保留下来,最好的方法是:当整数超过了安全范围的时候,使用字符串表示。我们可以通过修改jsonlint.y来达到这个目的。
原本对JSONNumber的定义是
JSONNumber : NUMBER {$$ = Number(yytext);} ; 复制代码
在这里yytext是要进行解析的原始数据,$$是结果。我们可以修改成
JSONNumber : NUMBER {$$ = yytext == String(Number(yytext))? Number(yytext): yytext;} ; 复制代码
==> 生成我们要的 jsonlint.js:
git clone git://github.com/zaach/jsonlint.git cd src jison jsonlint.y jsonlint.l 复制代码
引入至项目
这里以Vue项目为例: 1、将自定义的 jsonlint.js 放到 static 目录下
2、在 index.html 中引入
<script src="./static/jsonlint/jsonlint.js"></script> 复制代码
3、在我们请求的返回数据中,做一层拦截转换 此处以 axios 的实现方法为例:
// transformResponse 选项允许我们在数据传送到 `then/catch` 方法之前对数据进行改动 axios.defaults.transformResponse = [ function(data) { return jsonlint.parse(data) } ] 复制代码
总结
综上,通过自定义JSON转化避免long类型数据溢出,可以实现long类型数据在前端正常显示。
注意:这个方法的确可以实现前端拿到的数据不出现精度丢失问题,但是再浏览器中的Preview上查看数据还是一个丢失的错误数据,这个是因为浏览器它用的还是自己原始的那个json parse方法。
后记:小伙伴们,如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果觉得本文还不错,记得点个赞哦! 本文首发地址为: Vae's Blog
以上所述就是小编给大家介绍的《Jison解决JS处理后端返回的Long型数据精度丢失问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 关于Jackson默认丢失Bigdecimal精度问题分析
- 拯救你丢失的精度——BigInteger和BigDecimal类(入门)
- Java 浮点型(Double,Float)精度丢失解决方案
- JS大坑之19位数的Number型精度丢失问题
- swagger-bootstrap-ui 1.9.6 发布,解决长整型精度丢失的问题
- JS计算精度小记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。