如何在Django中用生成器构建字典数组并输出合法JSON(StreamingHttpResponse)
解决Django StreamingHttpResponse流式输出合法JSON数组的问题
当然可以用生成器实现合法的JSON数组输出!你当前的代码只是逐个输出独立的JSON对象,没有处理数组的边界和元素间的分隔符,所以生成的内容不是有效的JSON格式。我们只需要调整生成器,分三个部分输出:数组开头的左括号、带逗号分隔的元素、数组结尾的右括号,同时保留流式输出的内存优势。
下面是修改后的完整代码:
import json from django.http import StreamingHttpResponse from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Image import logging logger = logging.getLogger(__name__) class Annotations(APIView): """流式输出标注数据为合法JSON数组""" def content_generator(self, request): # 先输出JSON数组的起始左括号 yield '[' image_objs = Image.objects.all().values("id","name","path") iterator = image_objs.iterator() first_item = True for image_obj in iterator: if not first_item: # 非第一个元素前输出逗号,实现元素间的分隔 yield ',' first_item = False image_data = { "name": image_obj["name"], "path": image_obj["path"] } yield json.dumps(image_data) # 最后输出JSON数组的结束右括号 yield ']' def get(self, request): try: response = StreamingHttpResponse(self.content_generator(request), content_type='application/json') response['Content-Disposition'] = 'attachment;filename="annotations.json"' return response except Exception as e: logger.exception("Error in getting annotations") return Response({'detail': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
关键修改说明:
- 数组边界处理:在生成器开头先输出
[,结尾输出],确保整体是一个合法的JSON数组结构 - 元素分隔符:用
first_item标记判断是否是第一个元素,非第一个元素前添加逗号,避免出现多余的前置或后置逗号 - 内存友好性:依然使用
iterator()方法遍历查询集,不会一次性把所有Image对象加载到内存中,完美适配流式输出的场景
额外注意:
- 如果查询集为空,生成器会输出
[],这是完全合法的空JSON数组 json.dumps会自动处理字符串的转义问题,确保每个对象的JSON格式正确- 这个方案完全基于生成器实现,没有额外引入第三方库,保持了代码的简洁性
内容的提问来源于stack exchange,提问作者Anurag Upadhyaya
相关产品推荐
相关产品推荐

