BigInt-safe JSON serialization and deserialization for Web3 data.
pnpm add json-web3
# or
npm i json-web3
# or
yarn add json-web3importjsonWeb3from'json-web3'constpayload={balance: 1234567890123456789n,decimals: 18n,u8Array: newUint8Array([1,2,3,255]),u16Array: newUint16Array([1,2,3,255]),bigIntArray: newBigInt64Array([18446744073709551615n,2n,3n,255n]),createdAt: newDate('2020-01-02T03:04:05.006Z'),ids: newSet([123,456]),headers: newMap([['hello','world']]),re: /([^\s]+)/g,url: newURL('https://example.com/'),fn: functionecho(arg){returnarg},}consttext=jsonWeb3.stringify(payload)// => {"balance":{"__@json.bigint__":"1234567890123456789"},"decimals":{"__@json.bigint__":"18"},"u8Array":{"__@json.typedarray__":{"type":"Uint8Array","bytes":"0x010203ff"}},"u16Array":{"__@json.typedarray__":{"type":"Uint16Array","bytes":"0x010002000300ff00"}},"bigIntArray":{"__@json.typedarray__":{"type":"BigInt64Array","bytes":"0xffffffffffffffff02000000000000000300000000000000ff00000000000000"}}}constrestored=jsonWeb3.parse(text)/* => { balance: 1234567890123456789n, decimals: 18n, u8Array: Uint8Array(4) [1, 2, 3, 255]..., u16Array: Uint16Array(4)..., bigIntArray: BigInt64Array(4)..., createdAt: Date(...), ids: Set(2) {...}, headers: Map(1) {...}, re: /([^\s]+)/g, url: URL(...), fn: undefined }*/consttextUnsafe=jsonWeb3.stringify_UNSAFE(payload)constrestoredUnsafe=jsonWeb3.parse_UNSAFE(textUnsafe)// restoredUnsafe.fn is a callable functionimportjsonWeb3from'json-web3'window.JSON=jsonWeb3// Yes, you can replace it directly; it is fully compatible.stringify(value, replacer?, space?)parse(text, reviver?)stringify_UNSAFE(value, replacer?, space?)(serializesFunctionpayloads)parse_UNSAFE(text, reviver?)(revivesFunctionpayloads vianew Function(...))
| type | supported by standard JSON? | supported by json-web3? |
|---|---|---|
string | ✅ | ✅ |
number | ✅ | ✅ |
boolean | ✅ | ✅ |
null | ✅ | ✅ |
Array | ✅ | ✅ |
Object | ✅ | ✅ |
undefined | ❌ | ❌ |
Infinity | ❌ | ✅ |
-Infinity | ❌ | ✅ |
NaN | ❌ | ✅ |
BigInt | ❌ | ✅ |
Date | ❌ | ✅ |
RegExp | ❌ | ✅ |
Set | ❌ | ✅ |
Map | ❌ | ✅ |
URL | ❌ | ✅ |
ArrayBuffer | ❌ | ✅ |
Uint8Array | ❌ | ✅ |
Uint8ClampedArray | ❌ | ✅ |
Uint16Array | ❌ | ✅ |
Uint32Array | ❌ | ✅ |
Int8Array | ❌ | ✅ |
Int16Array | ❌ | ✅ |
Int32Array | ❌ | ✅ |
Float16Array | ❌ | ✅ |
Float32Array | ❌ | ✅ |
Float64Array | ❌ | ✅ |
BigInt64Array | ❌ | ✅ |
BigUint64Array | ❌ | ✅ |
Function | ❌ | ✅ |
bigintvalues are encoded as objects:{"__@json.bigint__":"<value>"}.- Non-finite numbers (
NaN,Infinity,-Infinity) are encoded as{"__@json.number__":"<value>"}. Datevalues are encoded as{"__@json.date__":<timestamp>}.Mapvalues are encoded as{"__@json.map__":[[k,v],...]}andSetvalues as{"__@json.set__":[...]}.RegExpvalues are encoded as{"__@json.regexp__":{"source":"...","flags":"..."}}.URLvalues are encoded as{"__@json.url__":"..."}.Functionvalues are encoded as{"__@json.function__":"<source>"}bystringify_UNSAFEand are only revived byparse_UNSAFEusingnew Function(...)(using the UNSAFE function pair is dangerous; make sure your data is trusted).ArrayBuffervalues are encoded as{"__@json.arraybuffer__":{"bytes":"0x..."}}and decoded back toArrayBuffer.- Node
BufferJSON shapes and typed arrays are encoded as{"__@json.typedarray__":{"type":"<Name>","bytes":"0x..."}}and decoded back to the original typed array (Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,Int8Array,Int16Array,Int32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array).
Compared to libraries that require eval-based parsing (for example, serialize-javascript), this approach is generally safer and more efficient.
To enable cross-language interoperability, the serialization format is specified in RFC.md. It defines the canonical tag objects, payload shapes, validation rules, and UNSAFE function handling.