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

查看所有标签

猜你喜欢:

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

PHP程序设计

PHP程序设计

勒道夫 / 陈浩、胡丹、徐景 / 电子工业出版社 / 2009-3 / 80.00元

《PHP程序设计(第2版)》是最新版本PHP 5的权威指南,其中包含创建者PHP的创建者 Rasmus Lerdorf的独到的见解。《PHP程序设计(第2版)》以一种清晰而简练的风格介绍了PHP语言的语法和程序设计技术,并通过大量的示例演示了它们的正确使用方法和习惯用法。《PHP程序设计(第2版)》还给出了设计风格提示和实际的程序设计建议,这些将帮助你不仅成为一个PHP程序员,而且将是出色的PHP......一起来看看 《PHP程序设计》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换