使用jison解决JS处理后台返回的Number数据精度丢失

(一)前言

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

这个方法的确可以实现前端拿到的数据不出现精度丢失问题,但是再浏览器中的Preview上查看数据还是一个丢失的错误数据,这个是因为浏览器它用的还是自己原始的那个json parse方法

(二) 案例

api返回一个序列化的string,类似下面
使用jison解决JS处理后台返回的Number数据精度丢失_第1张图片
从上面可以看出js,float会失去精度,将2440.3499999999999转为2440.35

(三) 解决方案

我们不使用浏览器的JSON.parse, 自定义个parse,将number转为string,当然我们可以借助于jison。

  1. 安装依赖
yarn add jison --dev
  1. 新建文件
    使用jison解决JS处理后台返回的Number数据精度丢失_第2张图片
    jsonlint.l

代码如下

int  "-"?([0-9]|[1-9][0-9]+)
exp  [eE][-+]?[0-9]+
frac  "."[0-9]+

%%
\s+      /* skip whitespace */

{int}{frac}?{exp}?\b    return 'NUMBER'
\"(?:'\\'[\\"bfnrt/]|'\\u'[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*\"    yytext = yytext.substr(1,yyleng-2); return 'STRING'

"{"      return '{'
"}"      return '}'
"["      return '['
"]"      return ']'
","      return ','
":"      return ':'
"true"   return 'TRUE'
"false"  return 'FALSE'
"null"   return 'NULL'
<>  return 'EOF'
.        return 'INVALID'

%%

jsonlint.y

%start JSONText

/*
 ECMA-262 5th Edition, 15.12.1 The JSON Grammar.
 */


%%

JSONString
: STRING
{ // replace escaped characters with actual character
    $$ = yytext.replace(/\\(\\|")/g, "$"+"1")
    .replace(/\\n/g,'\n')
    .replace(/\\r/g,'\r')
    .replace(/\\t/g,'\t')
    .replace(/\\v/g,'\v')
    .replace(/\\f/g,'\f')
    .replace(/\\b/g,'\b');
}
;

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

JSONNullLiteral
: NULL
{$$ = null;}
;

JSONBooleanLiteral
: TRUE
{$$ = true;}
| FALSE
{$$ = false;}
;

JSONText
: JSONValue EOF
{return $$ = $1;}
;

JSONValue
: JSONNullLiteral
| JSONBooleanLiteral
| JSONString
| JSONNumber
| JSONObject
| JSONArray
;

JSONObject
: '{' '}'
{{$$ = {};}}
| '{' JSONMemberList '}'
{$$ = $2;}
;

JSONMember
: JSONString ':' JSONValue
{$$ = [$1, $3];}
;

JSONMemberList
: JSONMember
{{$$ = {}; $$[$1[0]] = $1[1];}}
| JSONMemberList ',' JSONMember
{$$ = $1; $1[$3[0]] = $3[1];}
;

JSONArray
: '[' ']'
{$$ = [];}
| '[' JSONElementList ']'
{$$ = $2;}
;

JSONElementList
: JSONValue
{$$ = [$1];}
| JSONElementList ',' JSONValue
{$$ = $1; $1.push($3);}
;

  1. 在package.json增加script
"jison": "cd jsonlint && jison jsonlint.y jsonlint.l",

在这里插入图片描述

  1. 生成jsonlint.js文件
yarn jiso
  1. 配置axios

使用jison解决JS处理后台返回的Number数据精度丢失_第3张图片

transformResponse: [(data) => {
    // Do whatever you want to transform the data
    return jsonlint.parse(data);
  }],
  1. 查看结果

在这里插入图片描述

我们可以看到,已经将返回的number转为string

(四) 总结

js还有失去精度问题,这时候需要big.js

相关代码,
git地址

相关cmmit
在这里插入图片描述

你可能感兴趣的:(ECMAScript,JS工具类)