Live data from Hacker News

JSON River – Parse JSON incrementally as it streams in

github.com

11–20 of 101 posts

Re: JSON River – Parse JSON incrementally as it streams in

#12
post #6

I can't imagine a usecase. Ok, you receive incremental updates, which could be useful, but how to find out that json object is actually received in full already?

When its closing brace or square bracket appears. EDIT: this is totally wrong and the question is right.

Actually, not quite how this works. You always get valid JSON, as in this sequence from the readme:

```json {"name": "Al"} {"name": "Ale"} ```

So the braces are always closed

Re: JSON River – Parse JSON incrementally as it streams in

#13

I don't get it (and I'd call this cumulative not incremental) Why not at least wait until the key is complete - what's the use in a partial key?

If you're building a UI that renders output from a streaming LLM you might get back something which looks like this:

  {"role": "assistant", "text": "Here's that Python code you aske
Incomplete parsing with incomplete strings is still useful in order to render that to your end user while it's still streaming in.

Re: JSON River – Parse JSON incrementally as it streams in

#15

Maybe I'm wrong but it seems like you would only want to parse partial values for objects and arrays, but not strings or numbers. Objects and arrays can be unbounded so it makes sense to process what you can, when you can, whereas a string or number usually is not.

It could be useful if you're doing something with the string that operates sequentially anyways (i.e. block-by-block AES, or SHA sums).

I _think_ the intended use of this is for people with bad internet connections so your UI can show data that's already been received without waiting for a full response. I.e. if their connection is 1KB/s and you send an 8KB JSON blob that's mostly a single text field, you can show them the first kilobyte after a second rather than waiting 8 seconds to get the whole blob.

At first I thought maybe it was for handling gigantic JSON blobs that you don't want to entirely load into memory, but the API looks like it still loads the whole thing into memory.

Re: JSON River – Parse JSON incrementally as it streams in

#16
post #13

I don't get it (and I'd call this cumulative not incremental) Why not at least wait until the key is complete - what's the use in a partial key?

If you're building a UI that renders output from a streaming LLM you might get back something which looks like this: {"role": "assistant", "text": "Here's that Python code you aske Incomplete parsing with incomplete strings is still useful in order to render that to your end user while it's still streaming in.

incomplete strings could be fun in certain cases

{"cleanup_cmd":"rm -rf /home/foo/.tmp" }

Re: JSON River – Parse JSON incrementally as it streams in

#17
For those wondering about the use case, this is very useful when enabling streaming for structured output in LLM responses, such as JSON responses. For my local Raspberry Pi agent I needed something performant, I've been using streaming-json-js [1], but development appears to have been a bit dormant over the past year. I'll definitely take a look at your jsonriver and see how it compares!

[1] https://github.com/karminski/streaming-json-js

Re: JSON River – Parse JSON incrementally as it streams in

#18
Oh, this is quite similar to an online parser I'd written a few years ago[1]. I have some worked examples on how to use it with the now-standard Chat Completions API for LLMs to stream and filter structured outputs (aka JSON). This is the underlying technology for a "Copilot" or "AI" application I worked on in my last role.

Like yours, I'm sure, these incremental or online parser libraries are orders of magnitude faster[2] than alternatives for parsing LLM tool calls for the very simple reason that alternative approaches repeatedly parse the entire concatenated response, which requires buffering the entire payload, repeatedly allocating new objects, and for an N token response, you parse the first token N times! All of the "industry standard" approaches here are quadratic, which is going to scale quite poorly as LLMs generate larger and larger responses to meet application needs, and users want low latency outputs.

One of the most useful features of this approach is filtering LLM tool calls on the server and passing through a subset of the parse events to the client. This makes it relatively easy to put moderation, metadata capture, and other requirements in a single tool call, while still providing low latency streaming UI. It also avoids the problem with many moderation APIs where for cost or speed reasons, one might delegate to a smaller, cheaper model to generate output in a side-channel of the normal output stream. This not only doesn't scale, but it also means the more powerful model is unaware of these requirements, or you end up with a "flash of unapproved content" due to moderation delays, etc.

I found that it was extremely helpful to work at the level of parse events, but recognize that building partial values is also important, so I'm working on something similar in Rust[3], but taking a more holistic view and building more of an "AI SDK" akin to Vercel's, but written in Rust.

[1] https://github.com/aaronfriel/fn-stream

[2] https://github.com/vercel/ai/pull/1883

[3] https://github.com/aaronfriel/jsonmodem

(These are my own opinions, not those of my employer, etc. etc.)

Re: JSON River – Parse JSON incrementally as it streams in

#19
post #6

I can't imagine a usecase. Ok, you receive incremental updates, which could be useful, but how to find out that json object is actually received in full already?

When you want to pull multi-gig JSON files and not wait for the full file before processing is where I first used this.

Re: JSON River – Parse JSON incrementally as it streams in

#20
post #5
post #4

Interesting approach. I would expect an object JSON stream to be more like a SAX parser though. It's familiar, fast and simple. Any thougts on not chosing the SAX approach?

I think this is a lot like etree in python's streaming approach for XML, but with a simpler API, and incremental text parsing. With etree in python, you can access the incomplete tree data and not have to worry about events. So it's missing the SAX API part of a SAX approach, but is built like some real world libraries that use the SAX approach, which end up having a hybrid of events and trees.

It seems to be convenient for some cases. A large object with many keys, for example.

I don't see it as particularly convenient if I want to stream a large array of small independent objects and read each one of them once, then discard it. The incremental parsed array would get bigger and bigger, eventually containing all the objects I wanted to discard. I would also need to move my array pointer to the last element at each increment.

jq and JSON.sh have similar incremental "mini-object-before-complete" approaches to parsing JSON. However, they do include some tools to shape those mini-objects (pruning, selecting, and so on). Also, they're tuned for pipes (new line is the event), which caters to shell and text-processing tools. I wonder what would be the analogue for that in a higher language.

Post reply on HN