json-bigint的json_parse源码分析

486 阅读1分钟

json-bigint是什么

解决js的精度丢失问题,它包含json_parse和json_stringify。

json_parse把json字符串转json对象的过程中,自动识别大整数,把大整数转成一个BigNumber对象来表示。

json_stringify 则可以把对象转为json。

源码

json-bigint: github.com/sidorares/j… 它内部依赖的bignumber.js: github.com/MikeMcl/big…

json_parse内部函数

var json_parse = function (options)函数是最外层,它返回了匿名函数 function (source, reviver)。而我们是使用这个匿名函数来处理json的。

    var result;
    
    text = source + '';
    at = 0;
    ch = ' ';
    
    result = value();
    
    white();

通过调用value函数来处理source中的值。

value = function () {
    // Parse a JSON value. It could be an object, an array, a string, a number,
    // or a word.

    white();
    switch (ch) {
      case '{':
        return object();
      case '[':
        return array();
      case '"':
        return string();
      case '-':
        return number();
      default:
        return ch >= '0' && ch <= '9' ? number() : word();
    }
  };

通过对传入的json的每一个字符做判断,来决定走哪一个分支函数。 只有是数字的才会走到number函数。

 number = function () {
    // Parse a number value.

    var number,
      string = '';

    if (ch === '-') {
      string = '-';
      next('-');
    }
    while (ch >= '0' && ch <= '9') {
      string += ch;
      next();
    }
    if (ch === '.') {
      string += '.';
      while (next() && ch >= '0' && ch <= '9') {
        string += ch;
      }
    }
    if (ch === 'e' || ch === 'E') {
      string += ch;
      next();
      if (ch === '-' || ch === '+') {
        string += ch;
        next();
      }
      while (ch >= '0' && ch <= '9') {
        string += ch;
        next();
      }
    }
    number = +string;
    if (!isFinite(number)) {
      error('Bad number');
    } else {
      if (BigNumber == null) BigNumber = require('bignumber.js');
      //if (number > 9007199254740992 || number < -9007199254740992)
      // Bignumber has stricter check: everything with length > 15 digits disallowed

      // const y = new BigNumber(1000000.0000)
      
      
      if (string.length > 15)
        return _options.storeAsString
          ? string
          : _options.useNativeBigInt
          ? BigInt(string)
          : new BigNumber(string);
      else
        return !_options.alwaysParseAsBig
          ? number
          : _options.useNativeBigInt
          ? BigInt(number)
          : new BigNumber(number);
    }
  },

Bignumber 有严格的校验: 不允许长度超过 15 位,因此我们对15位以上的数字转成BigNumber。