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 目录下

Jison解决JS处理后端返回的Long型数据精度丢失问题

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型数据精度丢失问题》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First JavaScript Programming

Head First JavaScript Programming

Eric T. Freeman、Elisabeth Robson / O'Reilly Media / 2014-4-10 / USD 49.99

This brain-friendly guide teaches you everything from JavaScript language fundamentals to advanced topics, including objects, functions, and the browser’s document object model. You won’t just be read......一起来看看 《Head First JavaScript Programming》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具