DEV Community

Discussion on: BigInt and JSON.stringify/JSON.parse

Collapse
 
webreflection profile image
Andrea Giammarchi

Interesting post, thanks, and it'd be great to have a common convention for all native constructors that can't be serialized, and these two helpers should already work for most cases (missing recursive parse/stringify for special cases such as Map or Set).

const serialize = value => `${
  value.constructor.name
}(${
  (typeof value === 'object' && (
    ('length' in value) || ('size' in value))
  ) ?
    `[${[...value].map(v => JSON.stringify(v))}]` :
    value
})`;

const unserialize = value => {
  const i = value.indexOf('(');
  const args = value.slice(i + 1, -1);
  const constructor = self[value.slice(0, i)];
  switch (constructor.name) {
    case 'BigInt':
      return constructor(args);
    default:
      return new constructor(JSON.parse(args));
  }
};
Enter fullscreen mode Exit fullscreen mode

Testable via:

unserialize(serialize(new Set([1, 2, 3])));
unserialize(serialize(new Map([['a', 1], ['b', 2]])));
unserialize(serialize(new Uint8Array([1, 2, 3])));
Enter fullscreen mode Exit fullscreen mode

In CircularJSON, differently from flatted, I used the ~ special char to signal recursion, but having a prefix such as \x01, or any other non common chars sequences, might be all it takes to have more portable data structures that can be resumed.