У меня есть поток объектов JSON, как у JSON-RPC через TCP или WebSockets. Там нет префикса длины или разделителя, потому что 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 всегда будет возвращать ровно одну отправку (что отлично работает для JSON-RPC через HTTP, но не через TCP или WebSockets, хотя, возможно, это может работать в локальных тестах, конечно). Другие фактически не обрабатывают JSON-RPC, потому что они добавляют требования к пробелам (некоторые из которых даже не применимы для JSON-RPC).
Я мог бы написать проверку разделителя, которая уравновешивает скобки и кавычки (обрабатывая экранирование и цитирование, конечно), или просто писать парсер JSON с нуля (или переносить один с другого языка или изменять http://code.google.com/p/json-sans-eval/), но я не могу поверить, что никто этого не делал раньше.
EDIT: я сам сделал две версии: http://pastebin.com/fqjKYiLw на основе json-sans-eval и http://pastebin.com/8H4QT82b на основе рекурсивного парсера регрессионного спуска в Crockford json_parse.js. Я бы предпочел использовать что-то, что было проверено и использовано другими людьми, а не само кодирование, поэтому я оставляю этот вопрос открытым.