UNPKG

json-canonicalize

Version:
87 lines (76 loc) 2.57 kB
export function canonicalize(obj: any, allowCircular?: boolean) { let buffer = '' const visited = new WeakMap<object, boolean>() serialize(obj) return buffer function serialize(object: any) { 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 += '[' let next = false object.forEach((element) => { if (next) { buffer += ',' } next = 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 += '{' const vKeys = Object.keys(object).filter((k)=> object[k] !== undefined).sort() vKeys.forEach((property, index) => addProp(object, property, index)) buffer += '}' } } function addProp(object: any, property: string, index: number) { if (index > 0) { buffer += ',' } /////////////////////////////////////////////// // Property names are strings - Use ES6/JSON // /////////////////////////////////////////////// buffer += JSON.stringify(property) buffer += ':' ////////////////////////////////////////// // Property value - Recursive expansion // ////////////////////////////////////////// serialize(object[property]) } }