Comments on: Streaming JSON with Flask https://blog.al4.co.nz/2016/01/streaming-json-with-flask/ My hobby... Fri, 26 Mar 2021 10:28:31 +0000 hourly 1 https://wordpress.org/?v=6.9.4 By: Alex Forbes https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-13191 Fri, 26 Mar 2021 09:43:30 +0000 https://blog.al4.co.nz/?p=2570#comment-13191 In reply to Le Loss.

This is practically invisible to the client, other than timing. It just means that the server can start transmitting without having to assemble the entire json blob in memory first, with the effect that the client sees a stready stream of data, rather than a long pause before the whole payload is dumped as fast as the network can transmit.

What I did here though wasn’t brilliant (it was a while ago….) – I constructed a JSON array which isn’t technically valid JSON until the final line is sent. So the client needs to read it as a whole anyway, but the chunk size wouldn’t be a factor, and the client code would be no different to the non-chunked approach.

Most systems doing this sort of job would send each chunk as an individually-valid JSON object, which is more reasonable with large amounts of data that would be expected to be handled individually.

edit: Technical term for this is ndjson, or new-line-delimited JSON: http://ndjson.org/

]]>
By: Le Loss https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-13190 Thu, 25 Mar 2021 18:09:06 +0000 https://blog.al4.co.nz/?p=2570#comment-13190 How do you requests.get(stream=True) this on the client side? Would you have to re-assemble the streamed unicode (with length given by chunk_size) into a valid json object? That sounds a bit counter-productive.

]]>
By: Rohith https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-13151 Wed, 07 Oct 2020 14:55:04 +0000 https://blog.al4.co.nz/?p=2570#comment-13151 Thank you, Alex! This was really helpful :)

I used a simple custom function to encode the date for json.

def json_serial(obj):
“””JSON serializer for objects not serializable by default json code”””
if isinstance(obj, datetime.datetime):
return obj.__str__()

json.dumps(to_dict(r), default=json_serial)

]]>
By: Alex Forbes https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-12888 Wed, 24 May 2017 15:43:41 +0000 https://blog.al4.co.nz/?p=2570#comment-12888 In reply to Sven.

Hi Sven glad it was useful. This looks like a solid improvement, I’ll probably integrate it into my implementation next time I work on it. Shame about the formatting but I’ll manage!

]]>
By: Sven https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-12887 Wed, 24 May 2017 15:02:42 +0000 https://blog.al4.co.nz/?p=2570#comment-12887 Well, the formatting went down the drain, I hope it makes sense anyway!

]]>
By: Sven https://blog.al4.co.nz/2016/01/streaming-json-with-flask/#comment-12886 Wed, 24 May 2017 15:01:59 +0000 https://blog.al4.co.nz/?p=2570#comment-12886 That was a very helpful post to quickly turn around a feature I’d think would take much longer. Thanks for sharing!

I’ve adjusted the logic for the iterator a bit to try and send the first item and then subsequently send ‘,’ + json(next item) (i.e. prefix the comma for sends after the first). I find that a bit clearer and it avoids having to keep the previous item around:

“`
def stream():
yield ‘[‘

reports = query.__iter__()
try:
r = next(reports)
yield json.dumps(to_dict(r), default=date_encoder)
except StopIteration:
# no results – close array and stop iteration
yield ‘]’
raise StopIteration

# loop over remaining results
for r in reports:
yield ‘,’ + json.dumps(to_dict(r), default=date_encoder)

# close array
yield ‘]’

return Response(stream(), content_type=’application/json’)
“`

Note I’m just sending a straight array instead of an dictionary with an array so the opening and closing elements are slightly different. I.e. replace `'[‘` with `'{“releases”: [‘` and `’]’` with `]}`.

]]>