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

Django REST Framework渲染含NaN/Inf浮点数的JSON合规性错误解决咨询

这个问题我之前也碰到过!核心原因是JSON规范本身不支持NaN、Infinity这类特殊浮点值,而DRF默认使用的JSON序列化器遵循严格的JSON标准,所以会抛出ValueError: Out of range float values are not JSON compliant错误。

给你几个可行的解决方案,按需选择:

方案1:自定义JSON编码器(推荐,DRF原生支持)

DRF允许我们替换默认的JSON编码器,我们可以继承DjangoJSONEncoder,在序列化前自动处理掉NaN和Inf:

from rest_framework.utils.json import DjangoJSONEncoder

class CustomJSONEncoder(DjangoJSONEncoder):
    def encode(self, obj):
        # 递归遍历数据,替换非JSON兼容的浮点值
        def sanitize_value(o):
            if isinstance(o, float):
                if o != o:  # 判断是否是NaN(NaN不等于自身)
                    return None  # 替换为null,也可以换成字符串"NaN"
                if o in (float('inf'), float('-inf')):
                    return None  # 替换为null,或字符串"inf"/"-inf"
            elif isinstance(o, dict):
                return {k: sanitize_value(v) for k, v in o.items()}
            elif isinstance(o, list):
                return [sanitize_value(item) for item in o]
            return o
        
        # 先清理数据再调用父类方法序列化
        sanitized_obj = sanitize_value(obj)
        return super().encode(sanitized_obj)

然后自定义一个JSON渲染器使用这个编码器:

from rest_framework.renderers import JSONRenderer

class CustomJSONRenderer(JSONRenderer):
    encoder_class = CustomJSONEncoder

最后在你的视图里替换默认的渲染器:

class BasicView(viewsets.ModelViewSet):
    # ... 其他原有配置
    renderer_classes = [CustomJSONRenderer, BrowsableAPIRenderer]

如果想全局生效,直接在settings.py里配置DRF的默认渲染器:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'your_app_name.renderers.CustomJSONRenderer',  # 替换成你的实际路径
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

方案2:手动清理返回数据(适合临时/局部场景)

如果只是某个视图需要处理,也可以在返回Response前手动遍历数据,替换掉特殊值:

def clean_non_json_data(data):
    if isinstance(data, dict):
        return {k: clean_non_json_data(v) for k, v in data.items()}
    elif isinstance(data, list):
        return [clean_non_json_data(item) for item in data]
    elif isinstance(data, float):
        if data != data:
            return None  # 或自定义业务需要的值
        if data in (float('inf'), float('-inf')):
            return None
    return data

# 在你的dashboard方法里使用:
@action(methods=['get'], url_path='dash', detail=False)
def dashboard(self, request):
    try:
        data = [{"k": 1, "v": float('nan')}, {"k": 2, "v": float('inf')}]
        cleaned_data = clean_non_json_data(data)  # 提前清理数据
        return Response({"data": cleaned_data})
    # ... 原有异常处理逻辑

方案3:修改JSON序列化器的strict参数(不推荐)

Python的json.dumps有个allow_nan参数,设置为True可以序列化NaN/Inf,但生成的内容其实不符合标准JSON规范,很多前端解析器会报错,所以不建议生产环境使用。如果只是测试用,可以通过自定义编码器实现:

class LenientJSONEncoder(DjangoJSONEncoder):
    def dumps(self, obj, **kwargs):
        kwargs.update({'allow_nan': True})
        return super().dumps(obj, **kwargs)

再次强调:这个方法会生成非标准JSON,可能导致前端或其他服务解析失败,谨慎使用!

总结一下,方案1是最规范的,能全局或局部解决问题,同时保证输出符合JSON标准;方案2适合只需要处理个别视图的场景。

内容的提问来源于stack exchange,提问作者jia Jimmy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 13:07:29