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

如何让Python json模块遇NaN时抛出JSONDecodeError而非ValueError?

解决Python JSON模块排除NaN时异常类型不一致的问题

默认情况下,在自定义parse_constant函数中抛出的ValueError不会被json模块自动转为JSONDecodeError,导致需要处理两种异常类型,且无法获取行号、位置等解析上下文信息。以下是两种可行的解决方法:

方案一:子类化JSONDecoder(推荐)

通过继承json.JSONDecoder并重写parse_constant方法,直接抛出包含精确位置信息的JSONDecodeError,完全贴合json模块的异常规范:

import json
from json.decoder import JSONDecodeError

class NoNaNDecoder(json.JSONDecoder):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.parse_constant = self._custom_parse_constant

    def _custom_parse_constant(self, constant_str: str):
        if constant_str == "NaN":
            # 获取解析器当前的位置和原始JSON文档
            pos = self.scanner.pos
            raise JSONDecodeError(
                "NaN is not valid JSON",
                self.raw_decode_doc,
                pos
            )
        # 其他常量(如Infinity、-Infinity)沿用默认处理逻辑
        return super().parse_constant(constant_str)

# 使用示例
some_json_string = '{"value": NaN}'
try:
    json_content = json.loads(some_json_string, cls=NoNaNDecoder)
except JSONDecodeError as e:
    print(f"解析错误:{e},行号:{e.lineno},列位置:{e.colno}")

这种方法能直接获取解析器的真实扫描位置,错误信息包含准确的行号和列号,是最可靠的实现方式。

方案二:包装json.loads调用(简单场景适用)

如果不想子类化解码器,可以在调用json.loads时捕获自定义的ValueError,手动构造JSONDecodeError。虽然无法获取解析器的精确位置,但可以通过正则匹配定位NaN的大致位置:

import json
from json.decoder import JSONDecodeError
import re

def loads_no_nan(json_str: str):
    def parse_constant(constant_str: str):
        if constant_str == "NaN":
            raise ValueError("NaN is not valid JSON")
        return float(constant_str)
    
    try:
        return json.loads(json_str, parse_constant=parse_constant)
    except ValueError as e:
        if str(e) == "NaN is not valid JSON":
            # 匹配JSON中的NaN常量(排除字符串内的NaN)
            match = re.search(r'(?<!")\bNaN\b(?!")', json_str)
            if match:
                pos = match.start()
                raise JSONDecodeError(str(e), json_str, pos) from e
        # 非自定义的ValueError原样抛出
        raise

# 使用示例
some_json_string = '{"value": NaN}'
try:
    json_content = loads_no_nan(some_json_string)
except JSONDecodeError as e:
    print(f"解析错误:{e}")

注意:该方法的正则匹配可能存在边缘情况(如嵌套结构中的NaN),仅适合简单场景使用。

内容的提问来源于stack exchange,提问作者Olivier Desenfans

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:31:42