var Parser = require('jsonparse') , Stream = require('stream').Stream , through = require('through') /* the value of this.stack that creationix's jsonparse has is weird. it makes this code ugly, but his problem is way harder that mine, so i'll forgive him. */ exports.parse = function (path) { var parser = new Parser() var stream = through(function (chunk) { if('string' === typeof chunk) { if (process.browser) { var buf = new Array(chunk.length) for (var i = 0; i < chunk.length; i++) buf[i] = chunk.charCodeAt(i) chunk = new Int32Array(buf) } else { chunk = new Buffer(chunk) } } parser.write(chunk) }, function (data) { if(data) stream.write(data) stream.queue(null) }) if('string' === typeof path) path = path.split('.').map(function (e) { if (e === '*') return true else if (e === '') // '..'.split('.') returns an empty string return {recurse: true} else return e }) var count = 0, _key if(!path || !path.length) path = null parser.onValue = function () { if (!this.root && this.stack.length == 1) stream.root = this.value if(! path) return var i = 0 // iterates on path var j = 0 // iterates on stack while (i < path.length) { var key = path[i] var c j++ if (key && !key.recurse) { c = (j === this.stack.length) ? this : this.stack[j] if (!c) return if (! check(key, c.key)) return i++ } else { i++ var nextKey = path[i] if (! nextKey) return while (true) { c = (j === this.stack.length) ? this : this.stack[j] if (!c) return if (check(nextKey, c.key)) { i++; break} j++ } } } if (j !== this.stack.length) return count ++ if(null != this.value[this.key]) stream.queue(this.value[this.key]) delete this.value[this.key] } parser._onToken = parser.onToken; parser.onToken = function (token, value) { parser._onToken(token, value); if (this.stack.length === 0) { if (stream.root) { if(!path) stream.queue(stream.root) stream.emit('root', stream.root, count) count = 0; stream.root = null; } } } parser.onError = function (err) { stream.emit('error', err) } return stream } function check (x, y) { if ('string' === typeof x) return y == x else if (x && 'function' === typeof x.exec) return x.exec(y) else if ('boolean' === typeof x) return x else if ('function' === typeof x) return x(y) return false } exports.stringify = function (op, sep, cl) { if (op === false){ op = '' sep = '\n' cl = '' } else if (op == null) { op = '[\n' sep = '\n,\n' cl = '\n]\n' } //else, what ever you like var stream , first = true , anyData = false stream = through(function (data) { anyData = true var json = JSON.stringify(data) if(first) { first = false ; stream.queue(op + json)} else stream.queue(sep + json) }, function (data) { if(!anyData) stream.queue(op) stream.queue(cl) stream.queue(null) }) return stream } exports.stringifyObject = function (op, sep, cl) { if (op === false){ op = '' sep = '\n' cl = '' } else if (op == null) { op = '{\n' sep = '\n,\n' cl = '\n}\n' } //else, what ever you like var stream = new Stream () , first = true , anyData = false stream = through(function (data) { anyData = true var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1]) if(first) { first = false ; stream.queue(op + json)} else stream.queue(sep + json) }, function (data) { if(!anyData) stream.queue(op) stream.queue(cl) stream.queue(null) }) return stream }