Skip to content

Instantly share code, notes, and snippets.

@joekim
Created December 7, 2011 03:12
Show Gist options
  • Save joekim/1441269 to your computer and use it in GitHub Desktop.
Save joekim/1441269 to your computer and use it in GitHub Desktop.
A simple carriage-return, line-feed delimited JSON protocol.
/*
A simple newline delimited JSON protocol.
Receiving Usage:
protocol = require('./json-protocol');
// parsing data
parser = protocol.StreamParser();
parser.on('message', function (msg) {
// handle message
});
socket.on('data', function (data) {
parser.read(data);
});
Sending Usage:
protocol = require('./frame-protocol');
socket.write(protocol.serialize({"hello": "world"}));
Based on code from:
https://gist.github.com/880514
https://github.com/joyent/node/blob/f44d0b90442d9a1dc7457924f827722fc3a7c440/lib/child_process.js#L71-141
*/
var util = require('util');
var events = require('events');
function StreamParser(){
if (!(this instanceof StreamParser)){
return new StreamParser();
}
events.EventEmitter.call(this);
this.buffer = '';
}
util.inherits(StreamParser, events.EventEmitter);
StreamParser.prototype.read = function(data){
this.buffer += data.toString(ENCODING);
var buffer = this.buffer;
var start = 0, msg, i;
while((i = buffer.indexOf(DELIMITER, start)) >= 0) {
var json = buffer.slice(start, i);
msg = null;
try {
msg = JSON.parse(json);
}
catch(err){
this.emit(ERROR, err);
}
if (msg){
this.emit(MESSAGE, msg);
}
start = i + 1;
}
if (start < buffer.length){
this.buffer = buffer.slice(start);
}
else {
this.buffer = '';
}
}
function serialize(message){
return JSON.stringify(message) + DELIMITER;
}
StreamParser.prototype.serialize = serialize;
/////////////////////////////////////////////////////////////////////////////
// Events
/////////////////////////////////////////////////////////////////////////////
var ERROR = 'error';
var MESSAGE = 'message';
StreamParser.prototype.ERROR = ERROR
StreamParser.prototype.MESSAGE = MESSAGE
/////////////////////////////////////////////////////////////////////////////
// Exports
/////////////////////////////////////////////////////////////////////////////
var DELIMITER = '\n';
var ENCODING = 'ascii';
exports.StreamParser = StreamParser;
exports.serialize = serialize;
exports.DELIMITER = DELIMITER;
exports.ENCODING = ENCODING;
/////////////////////////////////////////////////////////////////////////////
// Testing
/////////////////////////////////////////////////////////////////////////////
function testModule(){
var parser = new StreamParser();
parser.on(MESSAGE, function (msg) {
console.log('message: ', JSON.stringify(msg));
});
var msg = serialize({hi: true});
var part1 = msg.slice(0, 4);
var part2 = msg.slice(4);
console.log('serialized json: ' + JSON.stringify(msg));
console.log('part1: ' + part1);
console.log('part2: ' + part2);
parser.read(part1);
parser.read(part2);
}
if (require.main === module){
testModule();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment