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
相关产品推荐
相关产品推荐

