Package detail

json-stable-stringify

ljharb30.1mMIT1.3.0

deterministic JSON.stringify() with custom sorting to get deterministic hashes from stringified results

json, stringify, deterministic, hash

readme

json-stable-stringify Version Badge

github actions coverage License Downloads

npm badge

deterministic version of JSON.stringify() so you can get a consistent hash from stringified results

You can also pass in a custom comparison function.

example

const stringify = require('json-stable-stringify');

const obj = { c: 8, b: [{ z: 6, y: 5, x: 4 }, 7], a: 3 };

console.log(stringify(obj));

output:

{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}

methods

const stringify = require('json-stable-stringify')

const str = stringify(obj, opts)

Return a deterministic stringified string str from the object obj.

options

cmp

If opts is given, you can supply an opts.cmp to have a custom comparison function for object keys. Your function opts.cmp is called with these parameters:

opts.cmp({ key: akey, value: avalue }, { key: bkey, value: bvalue }, { get(key): value })

For example, to sort on the object key names in reverse order you could write:

const stringify = require('json-stable-stringify');

const obj = { c: 8, b: [{ z: 6, y: 5, x: 4 },7], a: 3 };

const s = stringify(obj, function (a, b) {
    return b.key.localeCompare(a.key);
});

console.log(s);

which results in the output string:

{"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3}

Or if you wanted to sort on the object values in reverse order, you could write:

const stringify = require('json-stable-stringify');

const obj = { d: 6, c: 5, b: [{ z: 3, y: 2, x: 1 }, 9], a: 10 };

const s = stringify(obj, function (a, b) {
    return a.value < b.value ? 1 : -1;
});

console.log(s);

which outputs:

{"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10}

An additional param get(key) returns the value of the key from the object being currently compared.

space

If you specify opts.space, it will indent the output for pretty-printing. Valid values are strings (e.g. {space: \t}) or a number of spaces ({space: 3}).

For example:

const obj = { b: 1, a: { foo: 'bar', and: [1, 2, 3] } };

const s = stringify(obj, { space: '  ' });

console.log(s);

which outputs:

{
  "a": {
    "and": [
      1,
      2,
      3
    ],
    "foo": "bar"
  },
  "b": 1
}

replacer

The replacer parameter is a function opts.replacer(key, value) that behaves the same as the replacer from the core JSON object.

install

With npm do:

npm install json-stable-stringify

license

MIT

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

v1.3.0 - 2025-04-21

Fixed

  • [New] add collapseEmpty option #15

Commits

  • [Dev Deps] update @arethetypeswrong/cli, @ljharb/tsconfig, @types/tape 1ac9c16
  • [Deps] update call-bound 729fcba

v1.2.1 - 2024-12-21

Commits

  • [types] input is unknown, can be non object 7135fba
  • [Dev Deps] update @arethetypeswrong/cli, @types/tape 504a644

v1.2.0 - 2024-12-17

Fixed

  • [readme] remove dead badges #14

Commits

  • [New] add types 5dbd6c8
  • [eslint] clean up formatting 21e95e5
  • [meta] sort package.json a9f44d5
  • [actions] split out node 10-20, and 20+ 74551e4
  • [Tests] add test coverage for options provided directly on a cmp function 0a50205
  • [Robustness] cache more builtins d390c99
  • [Dev Deps] update @ljharb/eslint-config, auto-changelog, tape 03686a0
  • [Tests] key ordering is reversed in node 11+ 7034a17
  • [Dev Deps] update npmignore, tape ba8d519
  • [Refactor] use call-bound directly 850b24c
  • [Tests] replace aud with npm audit 22fb720
  • [Deps] update call-bind adc30b0
  • [Deps] update call-bind a280582
  • [Dev Deps] add missing peer dep 3bb517c

v1.1.1 - 2024-01-16

Fixed

  • [Performance] use an array join instead of a string. #9

Commits

  • [readme] replaced var with const e22d419
  • [Dev Deps] update aud, tape dc26af2

v1.1.0 - 2023-11-13

Commits

  • [New] opts.cmp: add get function 1b11748
  • [meta] update license text so GitHub can identify it fd520e1
  • [Refactor] use isarray, object-keys instead of homegrown attempts d1d2038
  • [Refactor] build up a string instead of an array + join 6c066b8
  • [Refactor] avoid an IIFE 8243ea1
  • [Perf] avoid creating an options object when not needed 02f0778
  • [Refactor] avoid new Array 80d52a1
  • [Robustness] use call-bind to invoke replacer c52438f
  • [Robustness] cache JSON.stringify at module load 616dec3
  • [Dev Deps] update @ljharb/eslint-config, aud, tape 494a3ce
  • [Dev Deps] update @ljharb/eslint-config, aud, tape 861ea7d
  • [Refactor] avoid recreating default replacer 4e95ebb
  • [Tests] remove unused travis.yml 1226971
  • [meta] add missing engines.node 7a80ff6

v1.0.2 - 2022-11-07

Commits

  • [eslint] fix indentation and whitespace c97e78c
  • [eslint] more cleanup c162117
  • [meta] add auto-changelog 83934ff
  • [actions] add reusable workflows 7b24830
  • [readme] rename, add badges 5433588
  • [eslint] add eslint 7be6c27
  • [meta] create FUNDING.yml; add funding in package.json 6edbece
  • [meta] use npmignore to autogenerate an npmignore file b5d7d3a
  • [Dev Deps] update tape 2200cf1
  • [actions] update rebase action e41ac00
  • [meta] update URLs f17e490
  • Only apps should have lockfiles 4f052f4
  • add breaking test (acyclic detected as cyclic) 7f5f443
  • [meta] add safe-publish-latest ddb843f
  • [Tests] add aud in posttest 245c9bf
  • [Deps] update jsonify 7b79a68
  • fix conflict e43ca2a

v1.0.1 - 2016-02-02

Commits

  • Correctly stringify non-cyclic shared references c26c700

v1.0.0 - 2014-05-27

Commits

  • Added options.replacer for custom object serialization ccf5e63
  • document replacer 894f43b

v0.1.3 - 2014-05-27

Commits

  • Enable toJSON function to return different types de0debf

v0.1.2 - 2014-04-02

Commits

  • Should call 'toJSON' if it is defined on the object being stringified. c1de9d1
  • guard the reference a723f70
  • reindent 7ff314f

v0.1.1 - 2013-12-21

Commits

v0.1.0 - 2013-12-21

Commits

  • New “space” option to enable pretty printing (same as ES5) e6815c9
  • formatting 962edf4

v0.0.1 - 2013-07-17

Commits

v0.0.0 - 2013-07-17

Commits

  • docs, more examples 81f36c1
  • package.json etc 98c5fd6
  • working implementation with 2 examples 3e5363a
  • turn examples into tests, everything passes cccbd24
  • badges f8ff127
  • comparison test now passes 8ab93e2
  • failing custom comparison test 3af627d
  • fix object.keys shim 7c16662
  • fix for the other tests that don't use a cmp function f7b9a47