You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django流式返回字典时JSON格式失效的解决方法咨询

解决Django流式响应JSON格式非法的问题

你遇到的问题很典型——直接yield独立的JSON字典会导致多个JSON对象被无分隔地拼接在一起,而标准JSON要求整个响应只能有一个顶层值(对象或数组),所以第二次及之后的输出会让整个响应变成无效JSON。下面给你几种可行的解决方案:

方案1:使用JSON Lines(NDJSON)格式

JSON Lines是一种专门用于流式JSON的格式,规则很简单:每个JSON对象单独占一行,用换行符分隔。这种格式被很多数据处理工具支持,前端也容易实现逐行解析。

修改你的make_response方法,需要导入json模块,把每个字典序列化为JSON字符串后加上换行符再yield:

import json
import time

def make_response(self):
    for _ in range(0,3):
        some_dict = {"data": "some_data"}
        yield json.dumps(some_dict) + '\n'
        time.sleep(1)

然后在视图里更新content_type为更标准的JSON Lines类型:

from django.http import StreamingHttpResponse

def flights(request, query):
    req_obj = Flights.RequestObject(query)
    return StreamingHttpResponse(
        req_obj.make_response(),
        content_type="application/x-ndjson"
    )

前端处理思路:接收响应流时,按换行符分割每一行,对每行单独做JSON解析即可。

方案2:流式输出合法的JSON数组

如果你希望整个响应是一个标准的JSON数组(前端可以直接用JSON.parse解析),可以通过分步输出数组的结构来实现:先输出左括号[,然后依次输出每个JSON元素(注意元素间用逗号分隔),最后输出右括号]。

修改后的make_response方法:

import json
import time

def make_response(self):
    # 先输出数组开头
    yield '['
    first_item = True
    for _ in range(0,3):
        some_dict = {"data": "some_data"}
        if not first_item:
            # 非第一个元素前加逗号
            yield ','
        yield json.dumps(some_dict)
        first_item = False
        time.sleep(1)
    # 输出数组结尾
    yield ']'

视图里的content_type保持"application/json"即可,这样整个响应流式输出完成后是一个合法的JSON数组:

[{"data": "some_data"},{"data": "some_data"},{"data": "some_data"}]

优点:前端可以像处理普通JSON响应一样,等整个流接收完成后直接解析;如果需要实时处理,也可以用流式JSON解析器逐步读取内容。

方案3:使用Server-Sent Events(SSE)

如果你的场景是前端需要实时接收服务器推送的消息,可以用SSE——这是HTML5标准的服务器推送技术,专门针对这种流式消息场景设计。

修改make_response方法输出SSE格式的内容:

import json
import time

def make_response(self):
    for _ in range(0,3):
        some_dict = {"data": "some_data"}
        # SSE格式:data: 内容\n\n
        yield f'data: {json.dumps(some_dict)}\n\n'
        time.sleep(1)

视图里设置对应的content_type和响应头:

def flights(request, query):
    req_obj = Flights.RequestObject(query)
    response = StreamingHttpResponse(req_obj.make_response())
    response['Content-Type'] = 'text/event-stream'
    response['Cache-Control'] = 'no-cache'  # 禁止缓存
    response['Connection'] = 'keep-alive'
    return response

前端处理思路:使用浏览器原生的EventSource对象来接收消息,无需手动处理流解析:

const eventSource = new EventSource('/your-flights-url');
eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log(data);
};

优点:前端实现简单,自带重连机制,适合实时通知、进度更新等场景。


内容的提问来源于stack exchange,提问作者Rafael Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:29:28