如何在JS中解析流上的第一个JSON对象

aba*_*ert 17 javascript json

我有一个JSON对象流,就像通过TCP或WebSockets上的JSON-RPC一样.没有长度前缀或分隔符,因为JSON是自我分隔的.所以,当我从流中读取时,我可能会得到这样的结果:

{"id":1,"result":{"answer":23},"error":null}
{"id":2,"result":{"answer":42},"error":null}
{"id":3,"result":{"answ
Run Code Online (Sandbox Code Playgroud)

我需要逐个解析每个JSON对象.我不能用JSON.parse做到这一点,因为它只会在最后为无关数据抛出语法错误.

当然,通过这个例子,我可以逐行进行,但我不能依赖看起来那样的空白; JSON-RPC可以像这样容易:

{
  "id": 1, 
  "result": {
    "answer": 23
  },
  "error":null
} 
Run Code Online (Sandbox Code Playgroud)

或这个:

{"id":1,"result":{"answer":23},"error":null}{"id":2,"result":{"answer":42},"error":null}
Run Code Online (Sandbox Code Playgroud)

对于其他语言的大多数解析器,显而易见的答案是这样的(使用Python作为示例):

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

但我在JS中找不到类似的东西.我查看了我能找到的每个JS解析器,它们都有效地等同于JSON.parse.

我尝试查看各种JSON-RPC框架,看看他们如何处理这个问题,而他们却没有.他们中的许多人都认为recv总是会返回一个send(这对于JSON-RPC通过HTTP工作正常,但不适用于TCP或WebSockets - 当然,它可能在本地测试中起作用).其他人实际上并没有处理JSON-RPC,因为他们在空白上添加了需求(其中一些甚至对JSON-RPC都不起作用).

我可以编写一个分隔括号和引号的分隔符检查(当然是处理转义和引用),或者只是从头开始编写JSON解析器(或者从另一种语言编写端口1,或者修改http://code.google.com/p/json-sans-eval /),但我不敢相信之前没有人这样做过.

编辑:我已经做了两个版本的自己,http://pastebin.com/fqjKYiLw基于JSON的SAN-EVAL和http://pastebin.com/8H4QT82b基于Crockford的参考递归下降解析器json_parse.js.我仍然宁愿使用经过其他人测试和使用的东西,而不是自己编写代码,所以我将这个问题保持开放.

aba*_*ert 15

经过一个月的搜索替代品而没有找到任何有用的东西,我决定编写一堆不同的实现并测试它们,然后我修改了Crockford的参考递归下降解析器(如问题所述,可在此处获得)).

它不是最快的,但在我做的每一次测试中它都足够快.更重要的是,它可以捕获明显错误的JSON,当它与不完整的JSON不一致时,比大多数其他替代方案要好得多.最重要的是,它需要从众所周知且经过验证的代码库中进行非常简单的更改,这使我对其正确性更有信心.

尽管如此,如果有人知道一个比我更好的图书馆(并且只是被许多项目使用而不仅仅是我认为是一个重要的资格),我很想知道它.

  • @abernert:实际上,通过分割括号,我能够找到平均有12个猜测的有效块,每个猜测花费的时间不到1毫秒.如果每秒800个数据事件对你来说非常慢,那么你需要大大降低你的期望.还要考虑JSON.parse在C中运行,而用户级解析器运行速度要慢得多. (2认同)