Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
111 views
in Technique[技术] by (71.8m points)

javascript - How can I parse the first JSON object on a stream in JS

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 stream, I may end up with something like this:

{"id":1,"result":{"answer":23},"error":null}
{"id":2,"result":{"answer":42},"error":null}
{"id":3,"result":{"answ

I need to parse each JSON object one by one. I can't do this with JSON.parse, because it will just throw a syntax error for extraneous data at the end.

Of course with that example I could go line by line, but I can't rely on the whitespace looking like that; JSON-RPC can just as easily look like this:

{
  "id": 1, 
  "result": {
    "answer": 23
  },
  "error":null
} 

Or this:

{"id":1,"result":{"answer":23},"error":null}{"id":2,"result":{"answer":42},"error":null}

With most parsers in other languages, the obvious answer is something like this (using Python as an example):

buf = ''
decoder = json.JSONDecoder()
def onReadReady(sock):
  buf += sock.read()
  obj, index = decoder.raw_decode(buf)
  buf = buf[index:]
  if obj:
    dispatch(obj)

But I can't find anything similar in JS. I've looked at every JS parser I can find, and they're all effectively equivalent to JSON.parse.

I tried looking at various JSON-RPC frameworks to see how they handle this problem, and they just don't. Many of them assume that a recv will always return exactly one send (which works fine for JSON-RPC over HTTP, but not over TCP or WebSockets—although it may appear to work in local tests, of course). Others don't actually handle JSON-RPC because they add requirements on whitespace (some of which aren't even valid for JSON-RPC).

I could write a delimiter check that balances brackets and quotes (handling escaping and quoting, of course), or just write a JSON parser from scratch (or port one from another language, or modify http://code.google.com/p/json-sans-eval/), but I can't believe no one has done this before.

EDIT: I've made two versions myself, http://pastebin.com/fqjKYiLw based on json-sans-eval, and http://pastebin.com/8H4QT82b based on Crockford's reference recursive descent parser json_parse.js. I would still prefer to use something that's been tested and used by other people rather than coding it myself, so I'm leaving this question open.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...