如何将SQLAlchemy Automap查询结果转换为JSON?
解决SQLAlchemy Automap查询结果转JSON的TypeError问题
嘿,这个坑我之前踩过!你遇到的TypeError: 'person' object is not iterable,本质是因为Automap生成的ORM实例不是可迭代的字典对象,直接用dict(r)去转换肯定会报错。下面给你几种实用的解决办法:
方法1:手动构造字典(适合字段少的场景)
如果你的person表字段不多,直接手动提取需要的属性构造字典最直观,也能精准控制序列化的内容:
import simplejson as json from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import Session from sqlalchemy import create_engine Base = automap_base() engine = create_engine("mysql+pymysql://test:test@localhost/test") Base.prepare(engine, reflect=True) session = Session(engine) Person = Base.classes.person persons = session.query(Person).all() # 手动提取字段构造字典列表 person_dicts = [{"id": p.id, "name": p.name, "email": p.email} for p in persons] # 转JSON s = json.dumps(person_dicts) print(s)
方法2:用SQLAlchemy inspect工具自动提取字段(通用方案)
如果表字段很多,或者不想硬编码字段名,用SQLAlchemy的inspect模块可以自动获取模型的所有数据库字段:
import simplejson as json from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import Session from sqlalchemy import create_engine, inspect Base = automap_base() engine = create_engine("mysql+pymysql://test:test@localhost/test") Base.prepare(engine, reflect=True) session = Session(engine) Person = Base.classes.person # 定义通用的ORM转字典函数 def orm_obj_to_dict(obj): # 获取模型的所有数据库列属性 column_attrs = inspect(obj).mapper.column_attrs return {attr.key: getattr(obj, attr.key) for attr in column_attrs} persons = session.query(Person).all() person_dicts = [orm_obj_to_dict(p) for p in persons] s = json.dumps(person_dicts, default=str) # default=str处理日期等特殊类型 print(s)
这个方法会自动提取所有和数据库表对应的字段,不会包含ORM对象的额外属性,非常通用。
方法3:处理关联对象(如果有外键关联)
如果你的Person表关联了其他表(比如Address),序列化时需要避免循环引用,修改上面的函数就能支持关联对象的序列化:
def orm_obj_to_dict(obj, include_relations=False): # 提取基础字段 result = {attr.key: getattr(obj, attr.key) for attr in inspect(obj).mapper.column_attrs} if include_relations: # 处理关联对象 for rel in inspect(obj).mapper.relationships: related_obj = getattr(obj, rel.key) if related_obj: if isinstance(related_obj, list): # 一对多关系,递归处理每个对象 result[rel.key] = [orm_obj_to_dict(item) for item in related_obj] else: # 一对一关系 result[rel.key] = orm_obj_to_dict(related_obj) return result # 使用时传入include_relations=True来包含关联数据 person_dicts = [orm_obj_to_dict(p, include_relations=True) for p in persons] s = json.dumps(person_dicts, default=str)
注意事项
- 如果你的数据包含日期、时间等非JSON原生支持的类型,记得在
json.dumps里加上default=str来自动转换为字符串。 - 避免直接序列化整个ORM对象,不仅会报错,还可能意外序列化一些不需要的内部属性或引发循环引用问题。
内容的提问来源于stack exchange,提问作者Alexander Gorbenko
相关产品推荐
相关产品推荐

