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

Python中外部对象序列化为JSON格式的最佳方案咨询

问题说明

调用Client API拉取数据时,执行json.loads(api_response.results)抛出错误:TypeError('Object of type ExternalUnifiedEvent is not JSON serializable');

注:这个报错本质是JSON序列化(Python对象转JSON字符串)时无法识别第三方自定义类型导致的,仅会在调用json.dumps()时触发,json.loads()是JSON字符串转Python对象的反序列化方法,不会抛出这类错误,此处大概率是方法名笔误。

由于ExternalUnifiedEvent是第三方SDK返回的自定义类型,不在当前代码库定义范围内,因此没有直接调用序列化方法,而是手动拆解对象字段组装字典,后续通过json.dumps()处理后用POST请求发送,需要确认该实现是否为最优方案。
原有实现代码如下:

def get_data():
   try:
       api_response = client_api.get()
       data = []
       for i in api_reponse.results:
           e = {
               "event_id": i.event_id
               "event_type": i.event_type
               "properties": i.properties
            }
           data.append(e)
        return data
    except Exception as e:
        print(e)
headers = {"Content-Type": "application/json",}
payload = get_data()
response = requests.post(webhook_url, headers=headers, data=json.dumps(payload))
方案评估

手动字段映射的方式可以跑通,但不是最优解,且现有代码存在明显bug:

  • 存在低级语法/拼写错误:循环内变量名写为api_reponse,和上方定义的api_response拼写不一致,运行会直接抛出NameError;字典内的键值对之间缺少逗号分隔,会触发语法错误
  • 可维护性差:如果后续SDK返回的ExternalUnifiedEvent对象新增、删除需要传递的字段,必须手动修改映射逻辑,漏改就会出现字段丢失、字段冗余的问题
  • 异常处理逻辑缺失:捕获异常后仅打印错误,没有兜底返回值,上层调用拿到None后执行json.dumps(payload)会直接崩溃
  • 存在重复劳动:如果其他业务逻辑也需要处理ExternalUnifiedEvent类型对象,需要重复编写字段拆解代码
  • 冗余操作:手动调用json.dumps()、手动设置Content-Type头属于重复劳动,requests库本身自带相关参数可以自动处理
优化实现

优先复用SDK自带的序列化能力,绝大多数第三方SDK的自定义模型都会内置字典转换方法(pydantic模型的model_dump()、普通SDK模型的to_dict()、内置属性__dict__),不需要手动维护字段映射,适配性更强。优化后代码如下:

import json
import requests

def _serialize_event(event_obj):
    # 优先调用SDK自带的序列化方法,自动适配字段变更
    if hasattr(event_obj, "model_dump"):
        return event_obj.model_dump(exclude_none=True)
    if hasattr(event_obj, "to_dict"):
        return event_obj.to_dict()
    if hasattr(event_obj, "__dict__"):
        # 过滤掉对象内置的私有属性
        return {k: v for k, v in event_obj.__dict__.items() if not k.startswith("_")}
    # 兜底逻辑:以上方法都不存在时,再手动映射需要的字段
    return {
        "event_id": event_obj.event_id,
        "event_type": event_obj.event_type,
        "properties": event_obj.properties
    }

def get_data():
    try:
        api_response = client_api.get()
        data = []
        # 修复原代码拼写错误
        for item in api_response.results:
            data.append(_serialize_event(item))
        return data
    except Exception as e:
        print(f"拉取API数据失败: {str(e)}")
        # 兜底返回空列表,避免上层逻辑崩溃
        return []

payload = get_data()
if payload:
    # 直接用requests的json参数,自动完成序列化、设置请求头,不需要手动处理
    response = requests.post(webhook_url, json=payload)

优化点说明:

  • 抽离独立的序列化方法,全项目可复用,避免重复编写字段映射逻辑
  • 优先适配SDK原生序列化能力,后续SDK字段更新不需要手动修改代码,自动同步全量合法字段
  • 修复了原代码的拼写错误、语法错误
  • 异常处理增加兜底返回值,避免上层逻辑因接口拉取失败崩溃
  • 移除冗余的手动序列化、手动设置请求头操作,用requests内置的json参数自动处理,减少人为失误
  • 增加空payload判断,避免发送无意义的空请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:15:43