JSON stringify with custom key ordering based on a reference object
npm install json-orderedJSON stringify with custom key ordering based on a reference object.
Unlike json-stringify-stable which uses alphabetical ordering, json-ordered preserves the key order from a reference object. This is useful for maintaining consistent formatting across configuration files, API responses, or any scenario where you want new objects to match an existing key order.
``bash`
npm install json-ordered
`javascript`
import { stringify, stringifier } from 'json-ordered';
`javascript`
const { stringify, stringifier } = require('json-ordered');
`javascript
import { stringify } from 'json-ordered';
const reference = { z: 1, a: 2, m: 3 };
const target = { a: 10, z: 20, m: 30, b: 40 };
stringify(target, reference);
// '{"z":20,"a":10,"m":30,"b":40}'
//
// Keys from reference (z, a, m) come first in reference order,
// then new keys (b) are appended alphabetically
`
When stringifying multiple objects with the same key order, create a reusable function:
`javascript
import { stringifier } from 'json-ordered';
const stringify = stringifier({ name: '', age: 0, city: '' });
stringify({ city: 'NYC', name: 'Alice', age: 30 });
// '{"name":"Alice","age":30,"city":"NYC"}'
stringify({ age: 25, city: 'LA', name: 'Bob', country: 'USA' });
// '{"name":"Bob","age":25,"city":"LA","country":"USA"}'
`
Key ordering is preserved at every nesting level:
`javascript
import { stringify } from 'json-ordered';
const reference = {
z: 1,
config: { port: 8080, host: 'localhost', timeout: 5000 },
a: 2,
};
const target = {
a: 100,
config: { timeout: 3000, host: '0.0.0.0', port: 9000, ssl: true },
z: 200,
};
stringify(target, reference, 2);
// {
// "z": 200,
// "config": {
// "port": 9000,
// "host": "0.0.0.0",
// "timeout": 3000,
// "ssl": true
// },
// "a": 100
// }
`
Objects within arrays use the key order from the first object in the reference array:
`javascript
import { stringify } from 'json-ordered';
const reference = {
items: [{ z: 1, a: 2 }],
};
const target = {
items: [
{ a: 10, z: 20 },
{ a: 30, z: 40, extra: 50 },
],
};
stringify(target, reference);
// '{"items":[{"z":20,"a":10},{"z":40,"a":30,"extra":50}]}'
`
Pass a space argument (same as JSON.stringify):
`javascript`
stringify(target, reference, null, 2); // 2-space indent
stringify(target, reference, null, '\t'); // tab indent
Both functions support the replacer parameter from JSON.stringify:
`javascript
import { stringify, stringifier } from 'json-ordered';
// Replacer function - omit keys with value 0
stringify({ a: 1, b: 0, c: 3 }, { c: 0, b: 0, a: 0 }, (k, v) => v === 0 ? undefined : v);
// '{"c":3,"a":1}'
// Replacer array - only include specific keys
const s = stringifier({ z: 1, a: 2, m: 3 });
s({ a: 10, z: 20, m: 30 }, ['z', 'a']);
// '{"z":20,"a":10}'
`
Stringify an object using a reference object's key order.
| Parameter | Type | Description |
|-----------|------|-------------|
| obj | any | The object to stringify |referenceObj
| | any | The object whose key order should be used |replacer
| | function \| array \| null | Optional replacer (same as JSON.stringify) |space
| | string \| number | Optional indentation (same as JSON.stringify) |
Returns: string - JSON string with keys ordered according to the reference.
Creates a reusable stringify function with a cached key order map.
| Parameter | Type | Description |
|-----------|------|-------------|
| referenceObj | any | The object whose key order should be preserved |
Returns: (obj, replacer?, space?) => string - A stringify function
1. Reference keys first: Keys that exist in both reference and target are ordered according to the reference
2. New keys appended: Keys only in the target are appended alphabetically
3. Recursive ordering: Nested objects use key order from the corresponding nested reference object
4. Array handling: All objects in an array use the key order from the first object in the reference array
Keys in the reference but not in the target are simply skipped:
`javascript`
stringify({ a: 1 }, { z: 0, a: 0, m: 0 });
// '{"a":1}'
With an empty reference, keys are sorted alphabetically:
`javascript`
stringify({ z: 1, a: 2, m: 3 }, {});
// '{"a":2,"m":3,"z":1}'
JavaScript always iterates numeric keys in ascending order. This is a language limitation:
`javascript`
stringify({ '2': 'b', '1': 'a' }, { '2': '', '1': '' });
// '{"1":"a","2":"b"}' - numeric keys are always sorted
- null values are preservedundefined
- values are omitted (standard JSON behavior)Date
- objects are serialized as ISO strings
- Functions are omitted (standard JSON behavior)
Full TypeScript support with type declarations included.
`typescript
import { stringify, createOrderer } from 'json-ordered';
interface Config {
port: number;
host: string;
}
const ref: Config = { port: 8080, host: 'localhost' };
const target: Config = { host: '0.0.0.0', port: 9000 };
stringify(target, ref); // '{"port":9000,"host":"0.0.0.0"}'
``
MIT