Python读取含Decimal/datetime的类JSON数据报错,求解决方案
解决方法
你的问题核心是输入的字符串不是标准JSON,而是带有Python类型(Decimal、datetime.datetime)的类JSON结构,json.loads无法识别这些非JSON原生类型,所以解析阶段直接报错,object_hooks根本没机会生效。下面提供两种可行方案:
方案1:用ast.literal_eval解析后转换类型
ast.literal_eval可以安全解析Python字面量格式的字符串(包括Decimal、datetime的repr格式),先转成Python对象,再递归处理类型转换,最后转成标准JSON。
代码示例
import ast import json import decimal import datetime def convert_python_types(obj): # 递归处理嵌套结构 if isinstance(obj, dict): return {k: convert_python_types(v) for k, v in obj.items()} elif isinstance(obj, list): return [convert_python_types(item) for item in obj] # 转换Decimal为float elif isinstance(obj, decimal.Decimal): return float(obj) # 转换datetime为指定格式字符串 elif isinstance(obj, datetime.datetime): return obj.strftime("%Y-%m-%d %H:%M") # 其他类型保持原样 else: return obj # 示例输入字符串 raw_data_str = '{"value": Decimal("1.8333333"), "record_time": datetime.datetime(2023,9,21,12,0)}' # 步骤1:解析为Python对象 python_obj = ast.literal_eval(raw_data_str) # 步骤2:转换目标类型 converted_obj = convert_python_types(python_obj) # 步骤3:转为标准JSON字符串 final_json = json.dumps(converted_obj) print(final_json) # 输出:{"value": 1.8333333, "record_time": "2023-09-21 12:00"}
方案2:预处理字符串为标准JSON格式
如果输入的类JSON格式固定,可直接用正则替换掉Decimal和datetime的Python语法,转成JSON兼容格式后再用json.loads解析。
代码示例
import re import json import datetime def preprocess_to_json(raw_str): # 替换Decimal("x")为x(JSON数字格式) raw_str = re.sub(r'Decimal\("([\d\.]+)"\)', r'\1', raw_str) # 替换datetime.datetime(y,m,d,h,mi)为格式化后的字符串 def replace_datetime(match): year, month, day, hour, minute = map(int, match.groups()) dt = datetime.datetime(year, month, day, hour, minute) return f'"{dt.strftime("%Y-%m-%d %H:%M")}"' raw_str = re.sub(r'datetime\.datetime\((\d+),(\d+),(\d+),(\d+),(\d+)\)', replace_datetime, raw_str) return raw_str # 示例输入字符串 raw_data_str = '{"value": Decimal("1.8333333"), "record_time": datetime.datetime(2023,9,21,12,0)}' # 预处理为标准JSON格式 processed_str = preprocess_to_json(raw_data_str) # 解析为JSON对象 json_obj = json.loads(processed_str) print(json_obj) # 输出:{'value': 1.8333333, 'record_time': '2023-09-21 12:00'}
方案对比
- 方案1:通用性强,能处理任意嵌套结构,支持更多Python内置类型,
ast.literal_eval比eval更安全(不会执行恶意代码)。 - 方案2:性能略高,但依赖输入格式的绝对固定,若
Decimal或datetime的写法有变体(比如单引号、带秒数),需要调整正则规则。
内容的提问来源于stack exchange,提问作者Robert Hickman
相关产品推荐
相关产品推荐

