【发布时间】:2012-04-07 11:00:44
【问题描述】:
我有一个 JSON 对象流,例如基于 TCP 或 WebSockets 的 JSON-RPC。没有长度前缀或分隔符,因为 JSON 是自定界的。所以,当我从流中读取时,我可能会得到这样的结果:
{"id":1,"result":{"answer":23},"error":null}
{"id":2,"result":{"answer":42},"error":null}
{"id":3,"result":{"answ
我需要一一解析每个 JSON 对象。我不能用 JSON.parse 做到这一点,因为它只会在最后抛出无关数据的语法错误。
当然,对于那个例子,我可以逐行进行,但我不能依赖看起来像这样的空白; JSON-RPC 可以很容易地看起来像这样:
{
"id": 1,
"result": {
"answer": 23
},
"error":null
}
或者这个:
{"id":1,"result":{"answer":23},"error":null}{"id":2,"result":{"answer":42},"error":null}
对于大多数其他语言的解析器,显而易见的答案是这样的(以 Python 为例):
buf = ''
decoder = json.JSONDecoder()
def onReadReady(sock):
buf += sock.read()
obj, index = decoder.raw_decode(buf)
buf = buf[index:]
if obj:
dispatch(obj)
但是我在 JS 中找不到类似的东西。我查看了我能找到的每个 JS 解析器,它们都等效于 JSON.parse。
我尝试查看各种 JSON-RPC 框架以了解它们如何处理此问题,但它们没有。他们中的许多人假设 recv 将始终只返回一个发送(这适用于通过 HTTP 的 JSON-RPC,但不适用于通过 TCP 或 WebSockets ——当然,它可能在本地测试中工作)。其他人实际上并不处理 JSON-RPC,因为它们添加了对空格的要求(其中一些甚至对 JSON-RPC 无效)。
我可以编写一个分隔符检查来平衡括号和引号(当然,处理转义和引号),或者只是从头开始编写一个 JSON 解析器(或者从另一种语言移植一个,或者修改 http://code.google.com/p/json-sans-eval/),但我可以'不相信以前没有人这样做过。
编辑:我自己制作了两个版本,http://pastebin.com/fqjKYiLw 基于 json-sans-eval,http://pastebin.com/8H4QT82b 基于 Crockford 的参考递归下降解析器 json_parse.js。我仍然更愿意使用经过测试和其他人使用过的东西,而不是自己编写代码,所以我将这个问题留待解决。
【问题讨论】:
-
那么,您想像 SAX 解析 XML 那样解析 JSON 流吗?
-
不,不是。我不想对层次结构中的每个子对象进行回调,我只想获取每个顶级对象。 (我想 SAX 解析器足以构建我想要的东西,但绝对没有必要。)
-
我认为典型的 json-rpc 返回单个对象作为有效负载。这是您编写的自定义后端吗?如果你控制它,我可能会添加一个新的分隔符或者使用netstrings。
-
是的,JSON-RPC 返回单个对象作为有效负载,但这并不意味着 TCP 或 WebSockets 上的任何内容,因为它们没有任何有效负载的概念,只是一个流。 JSON-RPC 在有效负载之间没有任何分隔符,因为它是自定界的——只要你有一个 rawDecode 风格的函数。这就是我想要一个的原因。
-
并添加一个额外的分隔符(并在 JSON 中转义它),或者在套接字上的网络字符串上执行 JSON-RPC 而不是直接在套接字上的 JSON-RPC(这与使用长度前缀相同) ,我之前提到过),或任何类似的东西意味着它不再是 JSON-RPC,这意味着我不能对所有其他组件使用标准或现成的 JSON-RPC 代码。
标签: javascript json