json-stream-stringify
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -10,12 +10,12 @@ 'use strict'; | ||
class JSONStreamify extends CoStream { | ||
constructor(obj) { | ||
constructor(value, replacer) { | ||
super(arguments); | ||
this._iter = new RecursiveIterable(value, replacer); | ||
} | ||
* _makeGenerator(value) { | ||
let iter = new RecursiveIterable(value); | ||
* _makeGenerator(value, replacer) { | ||
let insertSeparator = false; | ||
for (let obj of iter) { | ||
for (let obj of this._iter) { | ||
if (obj.state === 'close') { | ||
yield this.push(obj.ctxType === Object ? '}' : ']'); | ||
yield this.push(obj.type === Object ? '}' : ']'); | ||
continue; | ||
@@ -26,3 +26,3 @@ } | ||
insertSeparator = false; | ||
yield this.push(obj.ctxType === Object ? '{' : '['); | ||
yield this.push(obj.type === Object ? '{' : '['); | ||
continue; | ||
@@ -61,3 +61,5 @@ } | ||
first = false; | ||
new JSONStreamify(data).once('end', () => next(null, undefined)).pipe(pass, { | ||
let stream = new JSONStreamify(data); | ||
stream._iter._forcedCtxType = Array; | ||
stream.once('end', () => next(null, undefined)).pipe(pass, { | ||
end: false | ||
@@ -84,7 +86,8 @@ }); | ||
} | ||
this._iter = undefined; | ||
} | ||
} | ||
module.exports = function (obj) { | ||
return new JSONStreamify(obj); | ||
module.exports = function (obj, replacer) { | ||
return new JSONStreamify(obj, replacer); | ||
}; |
{ | ||
"name": "json-stream-stringify", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "JSON.Stringify as a readable stream", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -78,3 +78,2 @@ # JSON Stream Stringify | ||
- Space option | ||
- Replacer option | ||
- Circular dependency detection/handling (infinite loops may occur as it is) | ||
@@ -81,0 +80,0 @@ |
@@ -7,3 +7,3 @@ 'use strict'; | ||
class RecursiveIterable { | ||
constructor(obj) { | ||
constructor(obj, replacer) { | ||
// Save a copy of the root object so we can be memory effective | ||
@@ -17,2 +17,3 @@ if (obj && typeof obj.toJSON === 'function') { | ||
this.obj = this._shouldIterate(obj) ? Array.isArray(obj) ? obj.slice(0) : Object.assign({}, obj) : obj; | ||
this.replacer = replacer instanceof Function ? replacer : undefined; | ||
} | ||
@@ -30,6 +31,6 @@ | ||
let isObject = this._shouldIterate(this.obj); | ||
let ctxType = RecursiveIterable._getType(this.obj); | ||
let nextIndex = 0; | ||
let keys = isObject && Object.keys(this.obj); | ||
let childIterator; | ||
let closed = !isObject; | ||
@@ -41,3 +42,3 @@ let opened = closed; | ||
depth: 0, | ||
type: RecursiveIterable._getType(this.obj), | ||
type: this._forcedCtxType || ctxType, | ||
next: () => { | ||
@@ -55,8 +56,11 @@ let child = childIterator && childIterator.next(); | ||
let val; | ||
let type; | ||
if (!opened) { | ||
state = 'open'; | ||
type = ctxType; | ||
opened = true; | ||
} else if (!closed && !keys.length) { | ||
state = 'close'; | ||
type = ctxType; | ||
closed = true; | ||
@@ -67,3 +71,13 @@ } else if (keys && keys.length) { | ||
val = this.obj[key]; | ||
} else if (!isObject && !ctx.done) { | ||
state = 'value'; | ||
val = this.obj; | ||
ctx.done = true; | ||
} | ||
if(state === 'value') { | ||
if (this.replacer) { | ||
val = this.replacer(key, val); | ||
} | ||
if (val && typeof val.toJSON === 'function') { | ||
@@ -73,2 +87,15 @@ val = val.toJSON(); | ||
if (val === undefined) { | ||
if (key) { | ||
// Dereference iterated object | ||
this.obj[key] = undefined; | ||
} | ||
if (ctx.type !== Array) { | ||
return ctx.next(); | ||
} | ||
val = null; | ||
} | ||
if (this._shouldIterate(val)) { | ||
@@ -82,8 +109,6 @@ state = 'child'; | ||
// Dereference iterated object | ||
this.obj[key] = undefined; | ||
} else if (!isObject && !ctx.done) { | ||
state = 'value'; | ||
val = this.obj; | ||
ctx.done = true; | ||
if (key) { | ||
// Dereference iterated object | ||
this.obj[key] = undefined; | ||
} | ||
} | ||
@@ -97,2 +122,3 @@ | ||
state: state, | ||
type: type, | ||
ctxType: ctx.type, | ||
@@ -99,0 +125,0 @@ attachChild: attachIterator |
27
test.js
@@ -8,6 +8,6 @@ 'use strict'; | ||
function createTest(input, expected) { | ||
function createTest(input, expected, replacer) { | ||
return () => new Promise((resolve, reject) => { | ||
let str = ''; | ||
new JSONStreamify(input).on('data', data => str += data.toString()).once('end', () => { | ||
new JSONStreamify(input, replacer).on('data', data => str += data.toString()).once('end', () => { | ||
try { | ||
@@ -19,3 +19,3 @@ expect(str).to.equal(expected); | ||
resolve(); | ||
}); | ||
}).once('error', reject); | ||
}); | ||
@@ -45,4 +45,21 @@ } | ||
it('1 should be 2', createTest(1, `2`, (k, v) => 2)); | ||
it('{} should be {}', createTest({}, '{}')); | ||
it('{a:undefined} should be {}', createTest({ | ||
a: undefined | ||
}, '{}')); | ||
it('{a:null} should be {"a":null}', createTest({ | ||
a: null | ||
}, '{"a":null}')); | ||
it('{a:undefined} should be {"a":1}', createTest({ | ||
a: undefined | ||
}, '{"a":1}', (k, v) => { | ||
expect(k).to.be('a'); | ||
return 1; | ||
})); | ||
it('{a:1} should be {"a":1}', createTest({ | ||
@@ -65,2 +82,4 @@ a: 1 | ||
it('[1, undefined, 2] should be [1,null,2]', createTest([1, undefined, 2], '[1,null,2]')); | ||
it(`[1,'a'] should be [1,"a"]`, createTest([1, 'a'], '[1,"a"]')); | ||
@@ -83,2 +102,4 @@ | ||
it(`ReadableStream('a', 'b', 'c') should be "abc"`, createTest(ReadableStream('a', 'b', 'c'), '"abc"')); | ||
it(`ReadableStream({}, 'a', undefined, 'c') should be [{},"a",null,"c"]`, createTest(ReadableStream({}, 'a', undefined, 'c'), '[{},"a",null,"c"]')); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18723
325
107