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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:34:55