json-ordered
JSON 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.
Installation
npm install json-orderedUsage
ES Modules
import { stringify, stringifier } from 'json-ordered';CommonJS
const { stringify, stringifier } = require('json-ordered');Basic Example
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 alphabeticallyReusable Stringifier
When stringifying multiple objects with the same key order, create a reusable function:
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"}'Nested Objects
Key ordering is preserved at every nesting level:
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
// }Arrays of Objects
Objects within arrays use the key order from the first object in the reference array:
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}]}'Pretty Printing
Pass a space argument (same as JSON.stringify):
stringify(target, reference, null, 2); // 2-space indent
stringify(target, reference, null, '\t'); // tab indentUsing a Replacer
Both functions support the replacer parameter from JSON.stringify:
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}'API
stringify(obj, referenceObj, replacer?, space?)
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.
stringifier(referenceObj)
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
How It Works
- Reference keys first: Keys that exist in both reference and target are ordered according to the reference
- New keys appended: Keys only in the target are appended alphabetically
- Recursive ordering: Nested objects use key order from the corresponding nested reference object
- Array handling: All objects in an array use the key order from the first object in the reference array
Edge Cases
Keys Missing from Target
Keys in the reference but not in the target are simply skipped:
stringify({ a: 1 }, { z: 0, a: 0, m: 0 });
// '{"a":1}'Empty Reference
With an empty reference, keys are sorted alphabetically:
stringify({ z: 1, a: 2, m: 3 }, {});
// '{"a":2,"m":3,"z":1}'Numeric Keys
JavaScript always iterates numeric keys in ascending order. This is a language limitation:
stringify({ '2': 'b', '1': 'a' }, { '2': '', '1': '' });
// '{"1":"a","2":"b"}' - numeric keys are always sortedSpecial Values
nullvalues are preservedundefinedvalues are omitted (standard JSON behavior)Dateobjects are serialized as ISO strings- Functions are omitted (standard JSON behavior)
TypeScript
Full TypeScript support with type declarations included.
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"}'License
MIT