Socket
Socket
Sign inDemoInstall

json-stream-stringify

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-stream-stringify - npm Package Compare versions

Comparing version 1.3.5 to 1.5.0

19

jsonStreamify.js

@@ -10,5 +10,5 @@ 'use strict';

class JSONStreamify extends CoStream {
constructor(value, replacer) {
constructor(value, replacer, space, _visited, _stack) {
super(arguments);
this._iter = new RecursiveIterable(replacer instanceof Function ? replacer(undefined, value) : value, replacer);
this._iter = new RecursiveIterable(replacer instanceof Function ? replacer(undefined, value) : value, replacer, space, _visited, _stack);
}

@@ -56,5 +56,6 @@

const pass = new PassThrough();
let i = 0;
obj.value.pipe(new Transform({
objectMode: true,
transform: function(data, enc, next) {
transform: (data, enc, next) => {
if (!first) {

@@ -64,3 +65,4 @@ pass.push(',');

first = false;
let stream = new JSONStreamify(data);
let stream = new JSONStreamify(data, this._iter.replacer, this._iter.space, this._iter.visited);
stream._iter._stack = obj.stack.concat(i++);
stream._iter._parentCtxType = Array;

@@ -77,4 +79,9 @@ stream.once('end', () => next(null, undefined)).pipe(pass, {

if (obj.state === 'circular') {
yield this.push(JSON.stringify({ $ref: `$${obj.value.map(v => `[${JSON.stringify(v)}]`).join('')}` }));
}
if (obj.value instanceof Promise) {
obj.value = obj.attachChild(new RecursiveIterable(yield obj.value)[Symbol.iterator]());
let childIterator = new RecursiveIterable(yield obj.value, this._iter.replacer, this._iter.space, this._iter.visited, obj.stack.concat(obj.key || []))[Symbol.iterator]();
obj.value = obj.attachChild(childIterator, obj.key);
insertSeparator = false;

@@ -94,4 +101,4 @@ continue;

module.exports = function (obj, replacer) {
module.exports = function(obj, replacer) {
return new JSONStreamify(obj, replacer);
};
{
"name": "json-stream-stringify",
"version": "1.3.5",
"version": "1.5.0",
"description": "JSON.Stringify as a readable stream",

@@ -5,0 +5,0 @@ "repository": {

@@ -93,3 +93,2 @@ # JSON Stream Stringify

- Space option
- Circular dependency detection/handling (infinite loops may occur as it is)

@@ -102,2 +101,4 @@ Feel free to contribute.

Circular structures are handled using a WeakMap based implementation of [Douglas Crockfords Decycle method](https://github.com/douglascrockford/JSON-js/blob/master/cycle.js). To restore circular structures; use Crockfords Retrocycle method on the parsed object.
## Requirements

@@ -104,0 +105,0 @@ NodeJS >4.2.2

@@ -7,3 +7,3 @@ 'use strict';

class RecursiveIterable {
constructor(obj, replacer) {
constructor(obj, replacer, space, visited, stack) {
// Save a copy of the root object so we can be memory effective

@@ -16,5 +16,15 @@ if (obj && typeof obj.toJSON === 'function') {

}];
this.obj = this._shouldIterate(obj) ? (Array.isArray(obj) ? obj.slice(0) : Object.assign({}, obj)) : obj;
this._stack = stack || [];
this.visited = visited || new WeakMap();
if (this._shouldIterate(obj)) {
this.isVisited = this.visited.has(obj);
if (!this.isVisited) {
// Save only unvisited stack to weakmap
this.visited.set(obj, this._stack.slice(0));
}
}
this.obj = this._shouldIterate(obj) && !this.isVisited ? (Array.isArray(obj) ? obj.slice(0) : Object.assign({}, obj)) : obj;
this.replacerIsArray = Array.isArray(replacer);
this.replacer = replacer instanceof Function || this.replacerIsArray ? replacer : undefined;
this.replacer = replacer instanceof Function || this.replacerIsArray ? replacer : undefined;
this.space = space;
}

@@ -34,3 +44,3 @@

let nextIndex = 0;
let keys = isObject && Object.keys(this.obj);
let keys = isObject && (Array.isArray(this.obj) ? Array.from(Array(this.obj.length).keys()) : Object.keys(this.obj));
let childIterator;

@@ -40,3 +50,7 @@ let closed = !isObject;

const attachIterator = iterator => childIterator = iterator;
const attachIterator = (iterator, addToStack) => {
childIterator = iterator;
childIterator._stack = this._stack.concat(addToStack || []);
};
const ctx = {

@@ -60,5 +74,12 @@ depth: 0,

if (!opened) {
state = 'open';
type = ctxType;
opened = true;
if (this.isVisited) {
state = 'circular';
val = this.visited.get(this.obj);
opened = closed = true;
keys.length = 0;
} else {
state = 'open';
type = ctxType;
opened = true;
}
} else if (!closed && !keys.length) {

@@ -82,7 +103,3 @@ state = 'close';

if(state === 'value') {
if (typeof val === 'function') {
return ctx.next();
}
if (state === 'value') {
if (this.replacer && !this.replacerIsArray) {

@@ -96,2 +113,6 @@ val = this.replacer(key, val);

if (typeof val === 'function') {
val = undefined;
}
if (val === undefined) {

@@ -111,7 +132,12 @@ if (key) {

if (this._shouldIterate(val)) {
state = 'child';
childIterator = new RecursiveIterable(val)[Symbol.iterator]();
childIterator.ctxType = ctx.type;
childIterator.depth = ctx.depth + 1;
childIterator.type = RecursiveIterable._getType(val);
if (this.visited.has(val)) {
state = 'circular';
val = this.visited.get(val);
} else {
state = 'child';
childIterator = new RecursiveIterable(val, this.replacer, this.space, this.visited, this._stack.concat(key))[Symbol.iterator]();
childIterator.ctxType = ctx.type;
childIterator.depth = ctx.depth + 1;
childIterator.type = RecursiveIterable._getType(val);
}
}

@@ -131,2 +157,3 @@

state: state,
stack: this._stack.slice(0),
type: type,

@@ -133,0 +160,0 @@ ctxType: ctx.type,

@@ -73,5 +73,7 @@ 'use strict';

it('{a:function(){}} should be {}', createTest({
a: function(){}
a: function() {}
}, '{}'));
it('[function(){}] should be [null]', createTest([function() {}], '[null]'));
it('{a:date} should be {"a":date.toJSON()}', createTest({

@@ -89,3 +91,4 @@ a: date

it('{a:[1], "b": 2} should be {"a":[1],"b":2}', createTest({
a: [1], b: 2
a: [1],
b: 2
}, '{"a":[1],"b":2}'));

@@ -95,3 +98,10 @@

it('[[[]],[[]]] should be [[[]],[[]]]', createTest([[[]],[[]]], '[[[]],[[]]]'));
it('[[[]],[[]]] should be [[[]],[[]]]', createTest([
[
[]
],
[
[]
]
], '[[[]],[[]]]'));

@@ -134,2 +144,28 @@ it('[1, undefined, 2] should be [1,null,2]', createTest([1, undefined, 2], '[1,null,2]'));

}, `{"a":[{"name":"name","arr":[],"date":"${date.toJSON()}"}]}`));
describe('circular structure', function() {
let circularData0 = {};
circularData0.a = circularData0;
it(`{ a: a } should be {"a":{"$ref":"$"}}`, createTest(circularData0, `{"a":{"$ref":"$"}}`));
let circularData1 = {};
circularData1.a = circularData1;
circularData1.b = [circularData1, {
a: circularData1
}]
circularData1.b[3] = ReadableStream(circularData1.b[1]);
it('{a: a, b: [a, { a: a },,ReadableStream(b.1)]} should be {"a":{"$ref":"$"},"b":[{"$ref":"$"},{"a":{"$ref":"$"}},null,[{"$ref":"$[\\"b\\"][1]"}]]}', createTest(circularData1, '{"a":{"$ref":"$"},"b":[{"$ref":"$"},{"a":{"$ref":"$"}},null,[{"$ref":"$[\\"b\\"][1]"}]]}'));
let circularData2 = {};
let data2 = {
a: 'deep'
};
circularData2.a = Promise.resolve({
b: data2
});
circularData2.b = data2;
it(`{ a: Promise({ b: { a: 'deep' } }), b: a.b } should be {"a":{"b":{"a":"deep"}},"b":{"$ref":"$[\\"a\\"][\\"b\\"]"}}`, createTest(circularData2, `{"a":{"b":{"a":"deep"}},"b":{"$ref":"$[\\"a\\"][\\"b\\"]"}}`));
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc