As soon as you pass your JSON string through JSON.parse, you'll lose precision because of the way floating point math works. You'll need to store the number as an object designed for storing arbitrary-precision numbers, and you'll need to fiddle with the string itself before parsing it. The simplest way is with regexes. JSON is a context free grammar, and regexes work on regular grammars, so the warning applies:
WARNING: PARSING CFG WITH REGEX MAY SUMMON ZALGO
This regex should turn the numbers in your JSON into strings:
let stringedJSON = origJSON.replace(/:s*([-+Ee0-9.]+)/g, ': "uniqueprefix$1"');
But I haven't tested it extensively and it definitely will screw things up if you have keys that are something like data:42
.
Assuming it worked correctly, stringedJSON
should now be something like {"foo": "uniqueprefix0.00000017", "bar": "an actual string"}
. You can parse this with JSON.parse
without losing precision, but uniqueprefix0.00000017
isn't what you want. JSON.parse
can be called with an extra reviver
argument, which transforms values passed to it before returning them. You can use this to convert your data back into a useful form:
let o = JSON.parse(stringedJSON, (key, value) => {
// only changing strings
if (typeof value !== 'string') return value;
// only changing number strings
if (!value.startsWith('uniqueprefix')) return value;
// chop off the prefix
value = value.slice('uniqueprefix'.length);
// pick your favorite arbitrary-precision library
return new Big(value);
});
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…