Skip to content

Instantly share code, notes, and snippets.

@adrai
Created October 20, 2017 05:54
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrai/713b298fd83da0063910aa9f1674a5ed to your computer and use it in GitHub Desktop.
Save adrai/713b298fd83da0063910aa9f1674a5ed to your computer and use it in GitHub Desktop.
const util = require('util');
const Transform = require('stream').Transform;
function Slicer (options) {
if (!(this instanceof Slicer)) {
return new Slicer(options);
}
Transform.call(this, options);
}
util.inherits(Slicer, Transform);
/**
* This function will be called from the supper class.
*
* Call `push(newChunk)` to pass along transformed output
* to the readable side. You may call 'push' zero or more times.
* Call `callback(err)` when you are done with this chunk. If you pass
* an error, then that'll put the hurt on the whole operation. If you
* never call callback(), then you'll never get another chunk.
*
* @param {Buffer} chunk Is an input chunk.
* @param {String} encoding The encoding for this chunk.
* @param {Function} callback The function, that will be called when this action is completed.
* `function(err){}`
* @private
*/
Slicer.prototype._transform = function (chunk, encoding, done) {
this.push(chunk);
done();
}
function getIdent(ident, level) {
var res = '';
for (var idx = 0; idx < (ident * level); idx++) {
res += ' ';
}
return res;
}
function transformObject(obj, stream, options, level) {
const nl = options.ident > 0 ? '\n' : '';
const space = options.ident > 0 ? ' ' : '';
const identation = getIdent(options.ident, level);
const identation2 = getIdent(options.ident, level + 1);
stream.write(`{`);
const keys = Object.keys(obj);
keys.forEach((k, i) => {
stream.write(`${nl}${identation2}"${k}":${space}`);
transformValue(obj[k], stream, options, level + 1);
if (i + 1 < keys.length) {
stream.write(',');
}
});
stream.write(`${nl}${identation}}`);
}
function transformValue(value, stream, options, level) {
const nl = options.ident > 0 ? '\n' : '';
// const space = options.ident > 0 ? ' ' : '';
const identation = getIdent(options.ident, level);
const identation2 = getIdent(options.ident, level + 1);
const type = Object.prototype.toString.call(value);
switch (type) {
case '[object Array]':
stream.write(`[`);
value.forEach((item, i) => {
stream.write(`${nl}${identation2}`);
transformValue(item, stream, options, level + 1);
if (i + 1 < value.length) {
stream.write(',');
}
});
stream.write(`${nl}${identation}]`);
break;
case '[object Object]':
transformObject(value, stream, options, level);
break;
case '[object Number]':
case '[object Boolean]':
case '[object String]':
case '[object Date]':
case '[object Null]':
case '[object Undefined]':
default:
stream.write(`${JSON.stringify(value)}`);
}
}
module.exports = (obj, options) => {
if (typeof obj !== 'object') throw new Error('Please pass an object!');
options = options || {};
options.ident = options.ident || 0;
const stream = new Slicer(options);
process.nextTick(() => {
transformObject(obj, stream, options, 0);
stream.end();
});
return stream;
};
@adrai
Copy link
Author

adrai commented Oct 20, 2017

usage:
jsonWriteStream(myLargeObject, { ident: 2 }).pipe(require('fs').createWriteStream('res.json'));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment