这两天在做小程序,发现后台返回Long类型时,js按照Number类型进行处理,那么这就会产生数据如果大于9007199254740992就会出现精度丢失,因为Long的范围是-9223372036854775808~9223372036854775808 (-2^63~2^63),而js中Number的范围为-9007199254740992~9007199254740992(-2^53 ~2^53),
有两种解决方案
1.后台Long转为String返回
但是由于小程序接口是用手机app的,如果改的话可能会导致app有问题,还有一个就是接口太多,几乎所有的id都用的Long类型返回,所以采用第二种方法
2.如果是Number就转换为String,再进行Json.parse()
因为小程序默认数据返回类型是json,所以要将默认类型设置为text,而后遍历每个节点的数据类型,如果是Number,大于2^53次方就直接转换为String
/**
* 请求
*/
_request(action, method, data, suc, fail, dataType) {
wx.request({
url: wx.getStorageSync('url') + action + "?method=" + method,
data: arguments[2] == undefined||arguments[2] == ""?"":data,
header: header,
method: "Post",
dataType:'text',
success: (res) => {
res.data = this.getRealJsonData(res.data)
},
fail: (e)=>{
wx.showToast({
icon: "none",
title: "请求失败,请检查网络"
});
return
},
complete:()=>{
setTimeout(function () {
wx.hideLoading()
}, 500)
}
})
}
/**
* 因为js中的Json.parse()会让Number数据类型精度丢失,因此这个自己写一下
*/
getRealJsonData(baseStr) {
if (!baseStr || typeof baseStr != 'string') return;
var jsonData = null;
try {
jsonData = JSON.parse(baseStr);
} catch (err) {
return null;
}
var needReplaceStrs = [];
this.loopFindArrOrObj(jsonData, needReplaceStrs);
needReplaceStrs.forEach(function (replaceInfo) {
var matchArr = baseStr.match(eval('/"' + replaceInfo.key + '":[0-9]{15,}/'));
if (matchArr) {
var str = matchArr[0];
var replaceStr = str.replace('"' + replaceInfo.key + '":', '"' + replaceInfo.key + '":"');
replaceStr += '"';
baseStr = baseStr.replace(str, replaceStr);
}
});
var returnJson = null;
try {
returnJson = JSON.parse(baseStr);
} catch (err) {
return null;
}
return returnJson;
}
/**
* 遍历对象类型的
*/
getNeedRpStrByObj(obj, needReplaceStrs) {
for (var key in obj) {
var value = obj[key];
// 大于这个数说明精度会丢失!
if (typeof value == 'number' && value > 9007199254740992) {
needReplaceStrs.push({ key: key });
}
this.loopFindArrOrObj(value, needReplaceStrs);
}
}
/**
* 判断数据类型
*/
getNeedRpStrByArr(arr, needReplaceStrs) {
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
this.loopFindArrOrObj(value, needReplaceStrs);
}
}
/**
* 递归遍历
*/
loopFindArrOrObj(value, needRpStrArr) {
var valueTypeof = Object.prototype.toString.call(value);
if (valueTypeof == '[object Object]') {
needRpStrArr.concat(this.getNeedRpStrByObj(value, needRpStrArr));
}
if (valueTypeof == '[object Array]') {
needRpStrArr.concat(this.getNeedRpStrByArr(value, needRpStrArr));
}
}