canonicalize
Advanced tools
Comparing version 1.0.8 to 2.0.0
@@ -8,15 +8,15 @@ /* jshint esversion: 6 */ | ||
const json = { | ||
'1': {'f': {'f': 'hi', 'F': 5}, '\n': 56.0}, | ||
'10': {}, | ||
1: { f: { f: 'hi', F: 5 }, '\n': 56.0 }, | ||
10: {}, | ||
'': 'empty', | ||
'a': {}, | ||
'111': [ | ||
a: {}, | ||
111: [ | ||
{ | ||
'e': 'yes', | ||
'E': 'no' | ||
e: 'yes', | ||
E: 'no' | ||
} | ||
], | ||
'A': {} | ||
A: {} | ||
}; | ||
console.log(JSON.canonicalize(json)); |
@@ -6,15 +6,28 @@ /* jshint esversion: 6 */ | ||
module.exports = function serialize (object) { | ||
if (object === null || typeof object !== 'object' || object.toJSON != null) { | ||
if (typeof object === 'number' && isNaN(object)) { | ||
throw new Error('NaN is not allowed'); | ||
} | ||
if (typeof object === 'number' && !isFinite(object)) { | ||
throw new Error('Infinity is not allowed'); | ||
} | ||
if (object === null || typeof object !== 'object') { | ||
return JSON.stringify(object); | ||
} | ||
if (object.toJSON instanceof Function) { | ||
return serialize(object.toJSON()); | ||
} | ||
if (Array.isArray(object)) { | ||
return '[' + object.reduce((t, cv, ci) => { | ||
const values = object.reduce((t, cv, ci) => { | ||
const comma = ci === 0 ? '' : ','; | ||
const value = cv === undefined || typeof cv === 'symbol' ? null : cv; | ||
return t + comma + serialize(value); | ||
}, '') + ']'; | ||
return `${t}${comma}${serialize(value)}`; | ||
}, ''); | ||
return `[${values}]`; | ||
} | ||
return '{' + Object.keys(object).sort().reduce((t, cv, ci) => { | ||
const values = Object.keys(object).sort().reduce((t, cv) => { | ||
if (object[cv] === undefined || | ||
@@ -25,4 +38,5 @@ typeof object[cv] === 'symbol') { | ||
const comma = t.length === 0 ? '' : ','; | ||
return t + comma + serialize(cv) + ':' + serialize(object[cv]); | ||
}, '') + '}'; | ||
return `${t}${comma}${serialize(cv)}:${serialize(object[cv])}`; | ||
}, ''); | ||
return `{${values}}`; | ||
}; |
{ | ||
"name": "canonicalize", | ||
"version": "1.0.8", | ||
"version": "2.0.0", | ||
"description": "JSON canonicalize function ", | ||
@@ -5,0 +5,0 @@ "main": "lib/canonicalize.js", |
@@ -1,2 +0,2 @@ | ||
[![Build Status](https://travis-ci.com/erdtman/canonicalize.svg?branch=master)](https://travis-ci.com/erdtman/canonicalize) | ||
[![Build Status](https://app.travis-ci.com/erdtman/canonicalize.svg?branch=master)](https://app.travis-ci.com/erdtman/canonicalize) | ||
[![Coverage Status](https://coveralls.io/repos/github/erdtman/canonicalize/badge.svg?branch=master)](https://coveralls.io/github/erdtman/canonicalize?branch=master) | ||
@@ -3,0 +3,0 @@ # canonicalize |
@@ -36,2 +36,75 @@ /* jshint esversion: 6 */ | ||
test('NaN in array', t => { | ||
try { | ||
const input = [NaN]; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'NaN is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('NaN in object', t => { | ||
try { | ||
const input = { key: NaN }; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'NaN is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('NaN single value', t => { | ||
try { | ||
const input = NaN; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'NaN is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('Infinity in array', t => { | ||
try { | ||
const input = [Infinity]; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'Infinity is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('Infinity in object', t => { | ||
try { | ||
const input = { key: Infinity }; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'Infinity is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('Infinity single value', t => { | ||
try { | ||
const input = -Infinity; | ||
JSON.canonicalize(input); | ||
t.fail(); | ||
} catch (error) { | ||
t.is(error.message, 'Infinity is not allowed'); | ||
t.pass(); | ||
} | ||
}); | ||
test('object in array', t => { | ||
const input = [{ b: 123, a: 'string' }]; | ||
const expected = '[{"a":"string","b":123}]'; | ||
const actual = JSON.canonicalize(input); | ||
t.is(actual, expected); | ||
}); | ||
test('empty object', t => { | ||
@@ -113,1 +186,17 @@ const input = {}; | ||
}); | ||
test('object with toJSON', t => { | ||
const input = { | ||
a: 123, | ||
b: 456, | ||
toJSON: function () { | ||
return { | ||
b: this.b, | ||
a: this.a | ||
}; | ||
} | ||
}; | ||
const expected = '{"a":123,"b":456}'; | ||
const actual = JSON.canonicalize(input); | ||
t.is(actual, expected); | ||
}); |
22686
302