【问题标题】:How can I get Django to return JsonResponse with no extra quotes or quote escapes?如何让 Django 返回没有额外引号或引号转义的 JsonResponse?
【发布时间】:2026-01-23 13:45:01
【问题描述】:

使用 Django 1.7,每当我在视图中返回以下 JsonResponse 位时:

from django.http import JsonResponse
token = "1$aEJUhbdpO3cNrXUmFgvuR2SkXTP9="
response = JsonResponse({"token": token})
return response

我从网络浏览器/cURL 收到以下 HTTP 响应:

"{\"token\": \"1$aEJUhbdpO3cNrXUmFgvuR2SkXTP9=\"}"

我想要的,以及我在 Django 1.3 中拥有的是这样的:

{"token": "1$aEJUhbdpO3cNrXUmFgvuR2SkXTP9="}

我有两个生产中的移动应用程序依赖于使用 Django 的私有 API,不幸的是,他们期待第二种响应,没有额外的引号(围绕整个 JSON 的引号使其成为字符串)并且没有引号逃跑。

我的问题是,是否有一些内置方法可以强制 Django 响应不转义 JSON 响应?

我编写了以下中间件来执行此操作,但是...这似乎是一种非常脆弱的蛮力处理方式:

class UnescapeJSON(object):
    def process_response(self, request, response):
        """
        Directly edit response object here, searching for and replacing terms
        in the html.
        """
        if re.search('^/api/.*', request.path):
            r = response.content
            r = r.replace('\\', '')
            r = r.lstrip('"')
            r = r.rstrip('"')
            response.content = r
        return response

所以我希望有更聪明的方法。

背景故事是我正在尝试将旧的遗留代码库从 Django 1.3 更新到 1.8。我目前在本地开发环境中使用 1.7。 Django 1.3 以正确的方式返回 JSON,没有额外的引号和反斜杠。

以这种方式返回 JSON 的好处是:

{"token": "1$aEJUhbdpO3cNrXUmFgvuR2SkXTP9="}

...是我使用jQuery.post({success:...}) 来处理这个JSON 响应,它会自动为我运行jQuery.parseJSON(),把它变成我可以用点符号访问的JSON 对象。

我不能只在客户端修复字符串并手动重新运行parseJSON(),因为这会涉及让我的所有用户升级他们的移动应用程序。

所以我必须将 JSON 格式化为上述格式,否则我的移动 API 会被严重破坏。

我应该补充一点信息。这个 API 使用的是 Django Piston :(。我使用的是我找到的 1.7x 兼容版本。我现在无法更换 Django REST Framework。相信我,我会尽快。

【问题讨论】:

  • 你在哪个 django subversion 上?我无法重现 1.7 上的错误
  • 这种行为没有意义,默认JsonResponse is safe:JsonResponse.__init__(data, encoder=DjangoJSONEncoder, safe=True, **kwargs)
  • 内容没有转义。无论您使用什么工具来显示内容,都将其显示为转义。
  • 有趣的是,我在 1.8 部署中使用 Django REST Framework 看到了这一点。我最近刚从 1.3 升级到 1.8。但是,我刚刚添加了 RESTful 支持,所以我不能声称这曾经有效。但有趣的是我在 Django REST 中看到的。如果我想出一个解决方案,我会在这里发布。

标签: python json django


【解决方案1】:

我在 1.8 部署中使用 Django REST Framework 看到了这一点。我最近刚从 1.3 升级到 1.8。但是,我直到 1.8 才获得 RESTful 支持,所以我不能声称这曾经有效(或无效)。

这个问题是由我创建 Python 字典,将它们序列化为 JSON 对象,然后在结果上调用 json.dumps() 引起的。最后一步,调用 json.dumps(),并将结果传递给 Response() 构造函数,这导致了一个用双引号括起来的字符串。

更改我的代码:

def get(self, request, year, month, day, format=None):
    resp = None
    date = datetime(int(year), int(month), int(day), 0, 0)
    clinics = Clinic.objects.all()
    for x in clinics:
        aDate = datetime(x.date.year, x.date.month, x.date.day)
        if date >= aDate and date <= aDate + timedelta(days=x.duration):
            resp = serializers.serialize("json", [x, ])
            struct = json.loads(resp)
            struct[0]["fields"]["id"] = x.id
            resp = json.dumps(struct[0]["fields"])
            break

    if resp == None:
        raise NotFound()
    return Response(resp)

def get(self, request, year, month, day, format=None):
    resp = None
    date = datetime(int(year), int(month), int(day), 0, 0)
    clinics = Clinic.objects.all()
    for x in clinics:
        aDate = datetime(x.date.year, x.date.month, x.date.day)
        if date >= aDate and date <= aDate + timedelta(days=x.duration):
            resp = serializers.serialize("json", [x, ])
            struct = json.loads(resp)
            struct[0]["fields"]["id"] = x.id
            resp = struct[0]["fields"]
            break

    if resp == None:
        raise NotFound()
    return Response(resp)

修复了 Django REST 中的问题(对我而言)。 (请注意,我分配 resp 的行是唯一需要更改的行)。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    对于那些在 Google 上找到此主题的人,请放弃 JsonResponse。如果你尝试使用 jsonp,你会被抛出错误

    "TypeError: 为了允许非dict对象被序列化设置 False 的安全参数”

    如果您将 safe 设置为 False,您将收到带有引号的响应,这将在客户端失败。而是

    return HttpResponse(response_data, content_type='application/json')
    

    【讨论】: