json.JSONDecoder 如何自定义处理 NaN / Infinity / -Infinity

发布时间 - 2026-01-25 00:00:00    点击率:
JSONDecoder默认不支持NaN和Infinity,因JSON标准禁止这些值;可通过object_hook或parse_float(需strict=False)实现兼容解析,但编码时仍需自定义处理。

JSONDecoder 默认不支持 NaN 和 Infinity

Python 的 json.JSONDecoder 在解析时遇到 NaNInfinity-Infinity 会直接报错:ValueError: Invalid value encountered: NaN(或类似提示)。这不是 bug,而是 JSON 标准本身禁止这些值 —— 它们不属于 RFC 7159 合法的 JSON 数字。

但实际中,不少后端(尤其是 JavaScript 环境)会输出带这些值的“类 JSON”字符串。若你必须接收并解析这类输入,就得绕过标准校验。

用 object_hook + float() 强转是最简方案

核心思路:在解析完每个对象(dict)后,遍历其所有字符串值,对匹配 "NaN""Infinity""-Infinity" 的项尝试用 float() 转换。Python 的 float() 原生支持这些字面量。

示例实现:

import json

def handle_nan_inf(obj): for key, value in obj.items(): if isinstance(value, str): if value in ("NaN", "Infinity", "-Infinity"): obj[key] = float(value) return obj

data = '{"x": "NaN", "y": "Infinity", "z": 42}' result = json.loads(data, object_hook=handle_nan_inf)

result == {'x': nan, 'y': inf, 'z': 42}

  • 仅作用于 dict 层级,不会递归处理嵌套 list 中的字符串;如需全覆盖,改用 object_hook + 深度遍历,或换用 parse_float
  • 注意 float("NaN") 返回的是 float('nan'),它不等于自身(nan == nanFalse),后续判断要用 math.isnan()
  • 此方式不改变原始 JSON 字符串结构,只在解析后做一次修正,开销小

用 parse_float 捕获所有数字字面量(含非法格式)

parse_float 参数会在 JSON 解析器遇到任何数字 token 时调用,包括那些本该失败的 NaN 字符串 —— 只要它们没被预校验拦住。关键在于:**必须配合 strict=False**,否则解析器在 tokenize 阶段就抛错了。

示例:

import json

def robust_float(s): try: return float(s) except ValueError:

可选:记录未知格式,或返回 None/0

    return float('nan')

data = '{"a": NaN, "b": Infinity}' result = json.loads(data, parse_float=robust_float, strict=False)

result == {'a': nan, 'b': inf}

  • strict=False 是前提,否则 parse_float 根本不会被触发
  • parse_float 接收的是原始 token 字符串(如 "NaN"),不是已解析的数字,所以能捕获非法字面量
  • 它对所有数字位置生效(dict 值、list 元素、嵌套任意深度),比 object_hook 更彻底
  • 副作用:也会处理合法数字字符串(如 "123"),若你的 robust_float 有额外逻辑,需先判断是否为特殊字面量

别忽略 JSONEncoder 的反向兼容问题

能解析 NaN 不代表能原样输出。Python 的 json.JSONEncoder 默认拒绝编码 float('nan'),会报 ValueError: Out of range float values are not JSON compliant

  • 若需导出,必须自定义 default 或继承 JSONEncoder,例如:default=lambda x: None if math.isnan(x) else x
  • 更常见做法是提前清洗数据:入库/传输前把 nan/inf 替换为 None 或特定哨兵值(如 "__NaN__"),避免序列化阶段出问题
  • 前后端约定比强行兼容更可靠 —— 比如统一用 null 表示缺失,用字符串 "inf" 表示无穷大

真正麻烦的从来不是怎么读进来,而是读进来之后,要不要、以及能不能再安全地写出去。


# javascript  # python  # java  # js  # json  # 编码  # 后端  # red 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  如何用低价快速搭建高质量网站?  Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面  Android滚轮选择时间控件使用详解  晋江文学城电脑版官网 晋江文学城网页版直接进入  php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】  如何选择PHP开源工具快速搭建网站?  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  深圳网站制作平台,深圳市做网站好的公司有哪些?  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  javascript基本数据类型及类型检测常用方法小结  CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  Android自定义listview布局实现上拉加载下拉刷新功能  使用Dockerfile构建java web环境  Laravel如何保护应用免受CSRF攻击?(原理和示例)  香港服务器部署网站为何提示未备案?  phpredis提高消息队列的实时性方法(推荐)  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  如何在阿里云ECS服务器部署织梦CMS网站?  Swift中switch语句区间和元组模式匹配  JavaScript模板引擎Template.js使用详解  音乐网站服务器如何优化API响应速度?  JS碰撞运动实现方法详解  Android中AutoCompleteTextView自动提示  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  如何在万网主机上快速搭建网站?  香港服务器WordPress建站指南:SEO优化与高效部署策略  EditPlus 正则表达式 实战(3)  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法  零基础网站服务器架设实战:轻量应用与域名解析配置指南  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  做企业网站制作流程,企业网站制作基本流程有哪些?  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Angular 表单中正确绑定输入值以确保提交与验证正常工作  简单实现Android验证码  教你用AI润色文章,让你的文字表达更专业  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  Laravel如何使用Telescope进行调试?(安装和使用教程)  Laravel如何使用Vite进行前端资源打包?(配置示例)  Laravel定时任务怎么设置_Laravel Crontab调度器配置  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  如何用狗爹虚拟主机快速搭建网站?  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复  绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信  北京的网站制作公司有哪些,哪个视频网站最好?  javascript日期怎么处理_如何格式化输出