diff --git a/index.js b/index.js index 79e5efa..e06e895 100755 --- a/index.js +++ b/index.js @@ -1,7 +1,8 @@ #! /usr/bin/env node var Parser = require('jsonparse') - , through = require('through') + , Transform = require('io-stream').Transform + , inherits = require('inherits') /* @@ -12,20 +13,22 @@ var Parser = require('jsonparse') */ -exports.parse = function (path, map) { - - var parser = new Parser() - var stream = through(function (chunk) { - if('string' === typeof chunk) - chunk = new Buffer(chunk) - parser.write(chunk) - }, - function (data) { - if(data) - stream.write(data) - stream.queue(null) +exports.parse = Parse; + +inherits(Parse, Transform) + +function Parse(path, map) { + if (!(this instanceof Parse)) + return new Parse(path, map) + + Transform.call(this, { + objectMode: true }) + var stream = this; + this.root = null; + var parser = this.parser = new Parser() + if('string' === typeof path) path = path.split('.').map(function (e) { if (e === '*') @@ -83,7 +86,7 @@ exports.parse = function (path, map) { var data = this.value[this.key] if(null != data) if(null != (data = map ? map(data, actualPath) : data)) - stream.queue(data) + stream.push(data) delete this.value[this.key] for(var k in this.stack) this.stack[k].value = null @@ -95,7 +98,7 @@ exports.parse = function (path, map) { if (this.stack.length === 0) { if (stream.root) { if(!path) - stream.queue(stream.root) + stream.push(stream.root) count = 0; stream.root = null; } @@ -109,7 +112,13 @@ exports.parse = function (path, map) { } - return stream +} + +Parse.prototype._transform = function (chunk, encoding, next) { + if('string' === typeof encoding) + chunk = new Buffer(chunk, encoding) + this.parser.write(chunk) + next() } function check (x, y) { @@ -124,75 +133,105 @@ function check (x, y) { return false } -exports.stringify = function (op, sep, cl, indent) { - indent = indent || 0 +exports.stringify = Stringify; + +inherits(Stringify, Transform) + +function Stringify(op, sep, cl, indent) { + if (!(this instanceof Stringify)) + return new Stringify(op, sep, cl, indent) + + Transform.call(this, { + objectMode: true + }) + + this.indent = indent || 0 if (op === false){ - op = '' - sep = '\n' - cl = '' + this.op = '' + this.sep = '\n' + this.cl = '' } else if (op == null) { - op = '[\n' - sep = '\n,\n' - cl = '\n]\n' + this.op = '[\n' + this.sep = '\n,\n' + this.cl = '\n]\n' + } else { + this.op = op + this.sep = sep + this.cl = cl } //else, what ever you like - var stream - , first = true - , anyData = false - stream = through(function (data) { - anyData = true - var json = JSON.stringify(data, null, indent) - 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) - }) + this.first = true + this.anyData = false +} + +Stringify.prototype._transform = function (data, _, next) { + this.anyData = true + var json = JSON.stringify(data, null, this.indent) + if(this.first) { + this.first = false; + this.push(this.op) + } + else this.push(this.sep) + + this.push(json) + next() +} - return stream +Stringify.prototype._flush = function (done) { + if(!this.anyData) + this.push(this.op) + this.push(this.cl) + done() } -exports.stringifyObject = function (op, sep, cl, indent) { - indent = indent || 0 +exports.stringifyObject = StringifyObject; + +inherits(StringifyObject, Transform) + +function StringifyObject (op, sep, cl, indent) { + if (!(this instanceof StringifyObject)) + return new StringifyObject(op, sep, cl, indent) + + Transform.call(this, { + objectMode: true + }) + + this.indent = indent || 0 if (op === false){ - op = '' - sep = '\n' - cl = '' + this.op = '' + this.sep = '\n' + this.cl = '' } else if (op == null) { - op = '{\n' - sep = '\n,\n' - cl = '\n}\n' + this.op = '{\n' + this.sep = '\n,\n' + this.cl = '\n}\n' } - //else, what ever you like - - var first = true - , anyData = false - stream = through(function (data) { - anyData = true - var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent) - if(first) { first = false ; this.queue(op + json)} - else this.queue(sep + json) - }, - function (data) { - if(!anyData) this.queue(op) - this.queue(cl) - - this.queue(null) - }) + this.first = true + this.anyData = false +} +StringifyObject.prototype._transform = function (data, _, next) { + this.anyData = true + var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, this.indent) + if(this.first) { this.first = false ; this.push(this.op)} + else this.push(this.sep) + this.push(json) + next() +} +StringifyObject.prototype._flush = function (done) { + if(!this.anyData) this.push(this.op) + this.push(this.cl) - return stream + done() } + if(!module.parent && process.title !== 'browser') { process.stdin .pipe(exports.parse(process.argv[2])) diff --git a/package.json b/package.json index 501ef9a..3ca1790 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "JSONStream", - "version": "1.0.1", + "name": "jsonstream2a", + "version": "2.0.3", "description": "rawStream.pipe(JSONStream.parse()).pipe(streamOfObjects)", - "homepage": "http://github.com/dominictarr/JSONStream", + "homepage": "http://github.com/calvinmetcalf/JSONStream", "repository": { "type": "git", - "url": "git://github.com/dominictarr/JSONStream.git" + "url": "git://github.com/calvinmetcalf/JSONStream.git" }, "keywords": [ "json", @@ -16,8 +16,9 @@ "parsing" ], "dependencies": { - "jsonparse": "~1.0.0", - "through": ">=2.2.7 <3" + "inherits": "^2.0.1", + "io-stream": "^2.0.2", + "jsonparse": "~1.0.0" }, "devDependencies": { "it-is": "~1", diff --git a/test/destroy_missing.js b/test/destroy_missing.js index 315fdc8..8bc8544 100644 --- a/test/destroy_missing.js +++ b/test/destroy_missing.js @@ -11,7 +11,7 @@ var server = net.createServer(function(client) { console.log('close') console.error('PASSED'); server.close(); - }); + }).on('data', function (){}) client.pipe(parser); var n = 4 client.on('data', function () { diff --git a/test/multiple_objects_error.js b/test/multiple_objects_error.js index 83d113b..fb42023 100644 --- a/test/multiple_objects_error.js +++ b/test/multiple_objects_error.js @@ -12,11 +12,13 @@ var server = net.createServer(function(client) { var parser = JSONStream.parse(); parser.on('error', function(err) { console.log(err); + console.error('PASSED') server.close(); }); parser.on('end', function() { console.log('END'); + console.log('FAILED') server.close(); }); client.pipe(parser); diff --git a/test/stringify-custom.js b/test/stringify-custom.js new file mode 100644 index 0000000..f866a18 --- /dev/null +++ b/test/stringify-custom.js @@ -0,0 +1,41 @@ + +var fs = require ('fs') + , join = require('path').join + , file = join(__dirname, 'fixtures','all_npm.json') + , JSONStream = require('../') + , it = require('it-is').style('colour') + + function randomObj () { + return ( + Math.random () < 0.4 + ? {hello: 'eonuhckmqjk', + whatever: 236515, + lies: true, + nothing: [null], + stuff: [Math.random(),Math.random(),Math.random()] + } + : ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]] + ) + } + +var expected = [] + , stringify = JSONStream.stringify('{"features": [', ',', ']}') + , es = require('event-stream') + , stringified = '' + , called = 0 + , count = 10 + , ended = false + +while (count --) + expected.push(randomObj()) + + es.connect( + es.readArray(expected), + stringify, + es.writeArray(function (err, lines) { + it(JSON.parse(lines.join(''))).deepEqual({ + features: expected + }) + console.error('PASSED') + }) + ) diff --git a/test/stringify.js b/test/stringify.js index b6de85e..20b9969 100644 --- a/test/stringify.js +++ b/test/stringify.js @@ -13,7 +13,7 @@ var fs = require ('fs') lies: true, nothing: [null], stuff: [Math.random(),Math.random(),Math.random()] - } + } : ['AOREC', 'reoubaor', {ouec: 62642}, [[[], {}, 53]]] ) } @@ -25,7 +25,7 @@ var expected = [] , called = 0 , count = 10 , ended = false - + while (count --) expected.push(randomObj()) @@ -34,7 +34,7 @@ while (count --) stringify, //JSONStream.parse([/./]), es.writeArray(function (err, lines) { - + it(JSON.parse(lines.join(''))).deepEqual(expected) console.error('PASSED') })