Serialise BigDecimal, BigNumber, BigInt etc. to and from JSON
What types, and what serialisation pattern, can I use to ensure I have arbitrary-precision numbers in my JavaScript program while it's running, but the state is serialised to / deserialised from JSON with a minimum of pain?
I am writing an application that makes heavy use of numbers with higher precision than allowed by the ECMAScript native Number
type. So I need to use a custom type (currently BigNumber
) to represent those values.
I am looking hungrily at the proposed BigInt
type, which when implemented as standard will be an improvement for many applications including the one I'm writing. However that won't help at all with JSON, which knows nothing about BigInt
any more than BigNumber
.
Whichever custom type I choose, there are many values of this type throughout the application state. So much that it's worth considering a custom hook in the serialisation / deserialisation layer that will handle transforming it to / from JSON.
Presumably the JSON document will have to represent the values as JSON native types (e.g. Object
or String
instances). How then, when de-serialising the entire complex application state, to reliably recognise and de-serialise those instances among all the others, to the correct value of the correct BigInt
or BigNumber
type?
How can I serialise that state, such that any BigNumber
(or insert some other arbitrary-precision number type) value reliably survives the serialisation / de-serialisation process, to correct values of the correct type?
javascript types json-deserialization
add a comment |
What types, and what serialisation pattern, can I use to ensure I have arbitrary-precision numbers in my JavaScript program while it's running, but the state is serialised to / deserialised from JSON with a minimum of pain?
I am writing an application that makes heavy use of numbers with higher precision than allowed by the ECMAScript native Number
type. So I need to use a custom type (currently BigNumber
) to represent those values.
I am looking hungrily at the proposed BigInt
type, which when implemented as standard will be an improvement for many applications including the one I'm writing. However that won't help at all with JSON, which knows nothing about BigInt
any more than BigNumber
.
Whichever custom type I choose, there are many values of this type throughout the application state. So much that it's worth considering a custom hook in the serialisation / deserialisation layer that will handle transforming it to / from JSON.
Presumably the JSON document will have to represent the values as JSON native types (e.g. Object
or String
instances). How then, when de-serialising the entire complex application state, to reliably recognise and de-serialise those instances among all the others, to the correct value of the correct BigInt
or BigNumber
type?
How can I serialise that state, such that any BigNumber
(or insert some other arbitrary-precision number type) value reliably survives the serialisation / de-serialisation process, to correct values of the correct type?
javascript types json-deserialization
add a comment |
What types, and what serialisation pattern, can I use to ensure I have arbitrary-precision numbers in my JavaScript program while it's running, but the state is serialised to / deserialised from JSON with a minimum of pain?
I am writing an application that makes heavy use of numbers with higher precision than allowed by the ECMAScript native Number
type. So I need to use a custom type (currently BigNumber
) to represent those values.
I am looking hungrily at the proposed BigInt
type, which when implemented as standard will be an improvement for many applications including the one I'm writing. However that won't help at all with JSON, which knows nothing about BigInt
any more than BigNumber
.
Whichever custom type I choose, there are many values of this type throughout the application state. So much that it's worth considering a custom hook in the serialisation / deserialisation layer that will handle transforming it to / from JSON.
Presumably the JSON document will have to represent the values as JSON native types (e.g. Object
or String
instances). How then, when de-serialising the entire complex application state, to reliably recognise and de-serialise those instances among all the others, to the correct value of the correct BigInt
or BigNumber
type?
How can I serialise that state, such that any BigNumber
(or insert some other arbitrary-precision number type) value reliably survives the serialisation / de-serialisation process, to correct values of the correct type?
javascript types json-deserialization
What types, and what serialisation pattern, can I use to ensure I have arbitrary-precision numbers in my JavaScript program while it's running, but the state is serialised to / deserialised from JSON with a minimum of pain?
I am writing an application that makes heavy use of numbers with higher precision than allowed by the ECMAScript native Number
type. So I need to use a custom type (currently BigNumber
) to represent those values.
I am looking hungrily at the proposed BigInt
type, which when implemented as standard will be an improvement for many applications including the one I'm writing. However that won't help at all with JSON, which knows nothing about BigInt
any more than BigNumber
.
Whichever custom type I choose, there are many values of this type throughout the application state. So much that it's worth considering a custom hook in the serialisation / deserialisation layer that will handle transforming it to / from JSON.
Presumably the JSON document will have to represent the values as JSON native types (e.g. Object
or String
instances). How then, when de-serialising the entire complex application state, to reliably recognise and de-serialise those instances among all the others, to the correct value of the correct BigInt
or BigNumber
type?
How can I serialise that state, such that any BigNumber
(or insert some other arbitrary-precision number type) value reliably survives the serialisation / de-serialisation process, to correct values of the correct type?
javascript types json-deserialization
javascript types json-deserialization
edited Nov 12 '18 at 5:23
bignose
asked Nov 12 '18 at 4:57
bignosebignose
15.9k114976
15.9k114976
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
One potential solution is the Granola library for Node.js.
granola provides a JSON compatible stringifier and parser with support for modern language and object primitives.
This would require:
- Convert the application from using
BigNumber
values toBigInt
values. - Wait for tools to support
BigInt
in the entire build tool chain.
add a comment |
If modifying the type (by adding a property to the prototype) is feasible, there is a toJSON
hook from JSON.stringify
, designed specifically to help custom types collaborate with JSON serialisation.
If an object being stringified has a property named
toJSON
whose value is a function, then thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
method when called will be serialized.
So you could add a new method to the BigNumber
class:
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'
You can then recognise those specific objects when de-serialising, using the reviver
parameter of JSON.parse
:
If a
reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (beginning with the most nested properties and proceeding to the original value itself) are individually run through thereviver
. Then it is called, with the object containing the property being processed asthis
, and with the property name as a string, and the property value as arguments. [If the return value is notundefined
], the property is redefined to be the return value.
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 ] , …
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53256165%2fserialise-bigdecimal-bignumber-bigint-etc-to-and-from-json%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
One potential solution is the Granola library for Node.js.
granola provides a JSON compatible stringifier and parser with support for modern language and object primitives.
This would require:
- Convert the application from using
BigNumber
values toBigInt
values. - Wait for tools to support
BigInt
in the entire build tool chain.
add a comment |
One potential solution is the Granola library for Node.js.
granola provides a JSON compatible stringifier and parser with support for modern language and object primitives.
This would require:
- Convert the application from using
BigNumber
values toBigInt
values. - Wait for tools to support
BigInt
in the entire build tool chain.
add a comment |
One potential solution is the Granola library for Node.js.
granola provides a JSON compatible stringifier and parser with support for modern language and object primitives.
This would require:
- Convert the application from using
BigNumber
values toBigInt
values. - Wait for tools to support
BigInt
in the entire build tool chain.
One potential solution is the Granola library for Node.js.
granola provides a JSON compatible stringifier and parser with support for modern language and object primitives.
This would require:
- Convert the application from using
BigNumber
values toBigInt
values. - Wait for tools to support
BigInt
in the entire build tool chain.
answered Nov 12 '18 at 5:16
bignosebignose
15.9k114976
15.9k114976
add a comment |
add a comment |
If modifying the type (by adding a property to the prototype) is feasible, there is a toJSON
hook from JSON.stringify
, designed specifically to help custom types collaborate with JSON serialisation.
If an object being stringified has a property named
toJSON
whose value is a function, then thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
method when called will be serialized.
So you could add a new method to the BigNumber
class:
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'
You can then recognise those specific objects when de-serialising, using the reviver
parameter of JSON.parse
:
If a
reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (beginning with the most nested properties and proceeding to the original value itself) are individually run through thereviver
. Then it is called, with the object containing the property being processed asthis
, and with the property name as a string, and the property value as arguments. [If the return value is notundefined
], the property is redefined to be the return value.
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 ] , …
add a comment |
If modifying the type (by adding a property to the prototype) is feasible, there is a toJSON
hook from JSON.stringify
, designed specifically to help custom types collaborate with JSON serialisation.
If an object being stringified has a property named
toJSON
whose value is a function, then thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
method when called will be serialized.
So you could add a new method to the BigNumber
class:
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'
You can then recognise those specific objects when de-serialising, using the reviver
parameter of JSON.parse
:
If a
reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (beginning with the most nested properties and proceeding to the original value itself) are individually run through thereviver
. Then it is called, with the object containing the property being processed asthis
, and with the property name as a string, and the property value as arguments. [If the return value is notundefined
], the property is redefined to be the return value.
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 ] , …
add a comment |
If modifying the type (by adding a property to the prototype) is feasible, there is a toJSON
hook from JSON.stringify
, designed specifically to help custom types collaborate with JSON serialisation.
If an object being stringified has a property named
toJSON
whose value is a function, then thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
method when called will be serialized.
So you could add a new method to the BigNumber
class:
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'
You can then recognise those specific objects when de-serialising, using the reviver
parameter of JSON.parse
:
If a
reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (beginning with the most nested properties and proceeding to the original value itself) are individually run through thereviver
. Then it is called, with the object containing the property being processed asthis
, and with the property name as a string, and the property value as arguments. [If the return value is notundefined
], the property is redefined to be the return value.
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 ] , …
If modifying the type (by adding a property to the prototype) is feasible, there is a toJSON
hook from JSON.stringify
, designed specifically to help custom types collaborate with JSON serialisation.
If an object being stringified has a property named
toJSON
whose value is a function, then thetoJSON()
method customizes JSON stringification behavior: instead of the object being serialized, the value returned by thetoJSON()
method when called will be serialized.
So you could add a new method to the BigNumber
class:
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'
You can then recognise those specific objects when de-serialising, using the reviver
parameter of JSON.parse
:
If a
reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (beginning with the most nested properties and proceeding to the original value itself) are individually run through thereviver
. Then it is called, with the object containing the property being processed asthis
, and with the property name as a string, and the property value as arguments. [If the return value is notundefined
], the property is redefined to be the return value.
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 ] , …
edited Nov 12 '18 at 7:03
answered Nov 12 '18 at 6:16
bignosebignose
15.9k114976
15.9k114976
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53256165%2fserialise-bigdecimal-bignumber-bigint-etc-to-and-from-json%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown