Если возможно изменение типа (путем добавления свойства к прототипу), существует toJSON
ловушка из JSON.stringify
, специально разработанная, чтобы помочь пользовательским типам взаимодействовать с сериализацией JSON.
Если объект, подлежащий строковой обработке, имеет свойство с именем toJSON
, значением которого является функция, то метод toJSON()
настраивает поведение строковой классификации JSON: вместо сериализуемого объекта значение, возвращаемое методом toJSON()
при вызове будет сериализовано.
Таким образом, вы можете добавить новый метод в класс BigNumber
:
BigNumber.prototype.toJSON = function toJSON(key) {
return {
_type: 'BigNumber',
_data: Object.assign({}, this),
};
};
state = {
lorem: true,
ipsum: "Consecteur non dibale",
dolor: new BigNumber(107.58),
sit: { spam: 5, eggs: 6, beans: 7 },
amet: false,
};
serialisedState = JSON.stringify(state);
console.debug("serialisedState:", serialisedState);
// → '{"lorem":true,"ipsum":"Consecteur non dibale","dolor":{"_type":"BigNumber","_data":{"s":1,"e":2,"c":[1,0,7,5,8]}},"sit":{"spam":5,"eggs":6,"beans":7},"amet":false}'
Затем вы можете распознать эти конкретные объекты при десериализации, используя параметр reviver
JSON.parse
:
Если указано reviver
, значение, вычисленное при разборе, будет преобразовано перед возвратом. В частности, вычисленное значение и все его свойства (начиная с самых вложенных свойств и заканчивая самим исходным значением) по отдельности проходят через reviver
. Затем вызывается объект, содержащий свойство, обрабатываемое как this
, с именем свойства в виде строки и значением свойства в качестве аргументов. [Если возвращаемое значение не undefined
], свойство переопределяется как возвращаемое значение.
function reviveFromJSON(key, value) {
let result = value;
if (
(typeof value === 'object' && value !== null)
&& (value.hasOwnProperty('_type'))) {
switch (value._type) {
case 'BigNumber':
result = Object.assign(new BigNumber(0), value._data);
}
}
return result;
}
state = JSON.parse(serialisedState, reviveFromJSON);
console.debug("state:", state);
// → { … dolor: BigNumber { s: 1, e: 2, c: [ 1, 0, 7, 5, 8 ] }, … }