I have a stream of JSON objects, as with JSON-RPC over TCP or WebSockets. There\'s no length prefix or delimiter, because JSON is self-delimiting. So, when I read from the s
Here is a simple JSON Object separator. It assumes that you receive a series of JSON objects (not array) and that are well formed.
function JSONObjectSepaator() {
this.onObject = function (JSONStr) {};
this.reset = function () {
this.brace_count = 0;
this.inString = false;
this.escaped = false;
this.buffer = "";
};
this.receive = function (S) {
var i;
var pos=0;
for (i = 0; i < S.length; i++) {
var c = S[i];
if (this.inString) {
if (this.escaped) {
this.escaped = false;
} else {
if (c == "\\") {
this.escaped = true;
} else if (c == "\"") {
this.inString = false;
}
}
} else {
if (c == "{") {
this.brace_count++;
} else if (c == "}") {
this.brace_count--;
if (this.brace_count === 0) {
this.buffer += S.substring(pos,i+1);
this.onObject(this.buffer);
this.buffer = "";
pos=i+1;
}
} else if (c == "\"") {
this.inString = true;
}
}
}
this.buffer += S.substring(pos);
};
this.reset();
return this;
}
To use it, you can do it this way:
var separator = new JSONObjectSepaator();
separator.onObject = function (o) {
alert("Object received: "+o);
};
separator.receive('{"id":1,"result":{"answer":23},"error":null, "x');
separator.receive('x":"\\\""}{"id":2,"result":{"answer":42},"error":null}{"id":');
separator.receive('3,"result":{"answer":43},"err{or":3}');
After a month of searching for alternatives and not finding anything useful, I decided to code up a bunch of different implementations and test them out, and I went with my modification of Crockford's reference recursive-descent parser (as described in the question, available here).
It wasn't the fastest, but it was more than fast enough in every test I did. More importantly, it catches clearly erroneous JSON, when that's not ambiguous with incomplete JSON, much better than most of the other alternatives. Most importantly, it required very few, and pretty simple, changes from a well-known and -tested codebase, which makes me more confident in its correctness.
Still, if anyone knows of a better library than mine (and just being used by lots of projects instead of just me would count as a major qualification), I'd love to know about it.