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

查看所有标签

猜你喜欢:

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

图解网站分析(修订版)

图解网站分析(修订版)

[日] 小川卓 / 沈麟芸 / 人民邮电出版社 / 2014-10 / 69.00元

本书以图配文,结合实例详细讲解了如何利用从网站上获取的各种数据了解网站的运营状况,如何从数据中攫取最有用的信息,如何优化站点,创造更大的网站价值。本书适合各类网站运营人员阅读。 第1 部分介绍了进行网站分析必备的基础知识。第2 部分详细讲解了如何明确网站现状,发现并改善网站的问题。第3 部分是关于流量获取和网站内渠道优化的问题。第4 部分介绍了一些更加先进的网站分析方法,其中详细讲解了如何分......一起来看看 《图解网站分析(修订版)》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具