json-canonicalize
Version:
JSON canonicalize function
194 lines (188 loc) • 8.11 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.JsonCanonicalize = {}));
}(this, (function (exports) { 'use strict';
function canonicalize(obj, allowCircular) {
var buffer = '';
var visited = new WeakMap();
serialize(obj);
return buffer;
function serialize(object) {
if (object === null ||
typeof object !== 'object' ||
object.toJSON != null) {
/////////////////////////////////////////////////
// Primitive data type - Use ES6/JSON //
/////////////////////////////////////////////////
buffer += JSON.stringify(object);
// } else if (object instanceof Date) {
// buffer += JSON.stringify(object);
}
else if (Array.isArray(object)) {
/////////////////////////////////////////////////
// Array - Maintain element order //
/////////////////////////////////////////////////
if (visited.has(object)) {
if (!allowCircular) {
throw new Error('Circular reference detected');
}
buffer += '"[Circular]"';
return;
}
visited.set(object, true);
buffer += '[';
var next_1 = false;
object.forEach(function (element) {
if (next_1) {
buffer += ',';
}
next_1 = true;
if (element === undefined) {
element = null;
}
/////////////////////////////////////////
// Array element - Recursive expansion //
/////////////////////////////////////////
serialize(element);
});
buffer += ']';
}
else {
/////////////////////////////////////////////////
// Object - Sort properties before serializing //
/////////////////////////////////////////////////
if (visited.has(object)) {
if (!allowCircular) {
throw new Error('Circular reference detected');
}
buffer += '"[Circular]"';
return;
}
visited.set(object, true);
buffer += '{';
var vKeys = Object.keys(object).filter(function (k) { return object[k] !== undefined; }).sort();
vKeys.forEach(function (property, index) { return addProp(object, property, index); });
buffer += '}';
}
}
function addProp(object, property, index) {
if (index > 0) {
buffer += ',';
}
///////////////////////////////////////////////
// Property names are strings - Use ES6/JSON //
///////////////////////////////////////////////
buffer += JSON.stringify(property);
buffer += ':';
//////////////////////////////////////////
// Property value - Recursive expansion //
//////////////////////////////////////////
serialize(object[property]);
}
}
function canonicalizeEx(obj, options) {
var buffer = '';
var vInclude = options && options.include;
var vExclude = options && options.exclude;
if (vExclude) {
if (typeof vExclude === 'string')
vExclude = [vExclude];
}
if (vInclude)
vInclude.sort();
var visited = new WeakMap();
var allowCircular = options && (options === null || options === void 0 ? void 0 : options.allowCircular);
serialize(obj);
return buffer;
function serialize(object, parent) {
if (object === null ||
typeof object !== 'object' ||
object.toJSON != null) {
/////////////////////////////////////////////////
// Primitive data type - Use ES6/JSON //
/////////////////////////////////////////////////
buffer += JSON.stringify(object);
// } else if (object instanceof Date) {
// buffer += JSON.stringify(object);
}
else if (Array.isArray(object)) {
/////////////////////////////////////////////////
// Array - Maintain element order //
/////////////////////////////////////////////////
if (visited.has(object)) {
if (!allowCircular) {
throw new Error('Circular reference detected');
}
buffer += '"[Circular]"';
return;
}
visited.set(object, true);
buffer += '[';
var next_1 = false;
object.forEach(function (element) {
if (next_1) {
buffer += ',';
}
next_1 = true;
/////////////////////////////////////////
// Array element - Recursive expansion //
/////////////////////////////////////////
serialize(element, object);
});
buffer += ']';
}
else {
/////////////////////////////////////////////////
// Object - Sort properties before serializing //
/////////////////////////////////////////////////
if (visited.has(object)) {
if (!allowCircular) {
throw new Error('Circular reference detected');
}
buffer += '"[Circular]"';
return;
}
visited.set(object, true);
buffer += '{';
if (!parent && vInclude) {
vInclude.forEach(function (property, index) {
if (!object.hasOwnProperty(property))
return;
addProp(object, property, index);
});
}
else {
var vKeys = Object.keys(object).sort();
vKeys.forEach(function (property, index) { return addProp(object, property, index); });
}
buffer += '}';
}
}
function addProp(object, property, index) {
if (vExclude && vExclude.length) {
for (var _i = 0, vExclude_1 = vExclude; _i < vExclude_1.length; _i++) {
var v = vExclude_1[_i];
if (v === property)
return;
}
}
if (index > 0) {
buffer += ',';
}
///////////////////////////////////////////////
// Property names are strings - Use ES6/JSON //
///////////////////////////////////////////////
buffer += JSON.stringify(property);
buffer += ':';
//////////////////////////////////////////
// Property value - Recursive expansion //
//////////////////////////////////////////
serialize(object[property], object);
}
}
exports.canonicalize = canonicalize;
exports.canonicalizeEx = canonicalizeEx;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=index.umd.js.map