Is there a way to parse partial/incomplete JSON strings into map/interface values? For example: {"name": "foo
becomes map[string]any{"name": "foo"}
The need for this arises when using OpenAI’s chat completion API with the stream option (link) and if you want to utilize JSON responses that uses functions (or tools) you get back SSE messages like below:
{"f
iel
d:":
"val
ue"}
Which means these messages should be concatenated on the consumer side and the complete string is going to be a valid JSON string only when stream finishes, but this makes it impossible to update the UI as the response comes in.
There is a library for this in JS and also in Python but could not yet find one for Go. Any ideas are appreciated!
2
Answers
You can declare a struct to contain a
json.RawMessage
, for example:and only parse the fields that are already complete (or received):
and then parse the remaining json back to the RawMessage:
The exact parsing you want isn’t possible, because who says
{"name": "foo
is{"name": "foo" ...
and not{"name": "foobar" ...
?As mentioned by coxley in comments, you can use
json.Decoder.Token()
to iterate over the JSON stream. The jsoniter package provides a wrapper around it (and the underlying code shows how you could do this yourself as well – it isn’t that hard). You could also look into something like bytedance/sonic which provides a whole bunch of JSON encoding/decoding tools, though that may well be overkill.The most basic variant what will parse each top level node one at a time would look something like this:
This will do what you’ve described in the question. If your needs are more complicated (eg you need to get chunks at a deeper level) you’ll need to add some recursion – jsoniter shows a nice and simple way to do that (or just use that library).