Django JsonResponse 将数字转换为字符串

Django JsonResponse converts numbers to string

我正在从我的 Django 后端 API 使用 JsonResponse(status=200, data=<python_dict_with_data>) 到 return。然而,在检查结果时,所有数值都被转换为字符串(这些值是字典的值部分,而不是键)。这会在接收此响应的前端产生问题,因为现在我必须将它们解析为整数以进行格式化和轻量级计算。当从 Django returned 时,有没有办法阻止这种转换?

或者有没有办法在前端正确解析响应?我在前端的 React 中使用 Axios 库。

Is there a way to prevent this conversion when returned from Django?

键确实会被转换成字符串,因为整数作为键在JSON中是非法。事实上,如果你使用像 JSONLint 这样的验证器,你会看到 {1: 1} 是无效的 JSON,而 { "1": 1 } 是有效的 JSON。 Python JSON 编码器因此将回退到将整数转换为字符串,以仍然生成有效内容。

如果您必须进行轻量级计算,使用这些作为 keys 可能不是一个好主意。例如,如果您的数据如下所示:

{ 1: 4, 2: 5 }

您可以考虑重组数据,例如:

{ "data": [ {"key": 1, "value": 4}, {"key": 2, "value": 5} ] }

您也可以 return 它作为 HTTP 响应,并在 JavaScript 结束时进行解析,但可能只会导致更多麻烦。


对于Decimal个数字,它也会使用字符串。 Django 默认使用 DjangoJSONEncoder [Django-doc] which:

Decimal, Promise (django.utils.functional.lazy() objects), UUID: A string representation of the object.

例如,如果我们编码 Decimal,我们会看到:

>>> djenc = DjangoJSONEncoder()
>>> djenc.encode({'a': Decimal('0.25')})
'{"a": "0.25"}'

您可以将编码器子类化,并将 Decimal 解析为 float,但请注意,这可能会导致 精度损失 。这正是使用字符串的原因:确保没有数字丢失:

from django.core.serializers.json import DjangoJSONEncoder
from decimal import Decimal

class MyDjangoJSONEncoder(DjangoJSONEncoder):
    
    def <b>default</b>(self, o):
        if <b>isinstance(o, Decimal)</b>:
            return float(o)
        return super().default(o)

然后生成:

>>> mydjenc = MyDjangoJSONEncoder()
>>> mydjenc.encode({'a': Decimal('0.25')})
'{"a": 0.25}'

然后您可以在 JsonResponse:

中使用此编码器
from decimal import Decimal

def myview(request):
    # …
    JsonResponse(<b>encoder=MyDjangoJSONEncoder</b>, data={'a': Decimal('0.25')})