SQLAlchemy模型转JSON的多种方法
亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《SQLAlchemy模型转JSON:多方法高效解析指南》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下,希望所有认真读完的童鞋们,都有实质性的提高。

引言:SQLAlchemy 模型序列化挑战
在构建现代Web API时,将数据库中的数据(通常以ORM模型对象形式存在)转换为前端可理解的JSON格式是一个核心需求。对于简单的SQLAlchemy模型,直接将其属性映射到字典可能看似可行。然而,当模型涉及继承、一对多或多对多关系时,这种简单方法会遇到局限,例如无法自动包含关联表的数据。本文将介绍几种高效且推荐的方法,以解决SQLAlchemy模型,特别是包含复杂关系的模型,到JSON的序列化问题。
方案一:使用 SQLAlchemy-serializer Mixin
SQLAlchemy-serializer 是一个为 SQLAlchemy 模型提供便捷序列化功能的扩展。它通过一个 SerializerMixin 混合类,允许模型直接调用 to_dict() 方法来生成字典表示,并支持深度序列化和循环引用控制。
实现步骤
- 安装:
pip install SQLAlchemy-serializer
- 集成: 让你的 DeclarativeBase 或具体模型继承 SerializerMixin。
- 序列化: 直接调用模型实例的 to_dict() 方法。
- 控制递归: 使用 serialize_rules 属性来定义序列化规则,例如排除某些字段或限制关联对象的深度,以避免无限递归。
示例代码
import json
from sqlalchemy import ForeignKey, create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, sessionmaker
from sqlalchemy_serializer import SerializerMixin
# 基础模型类,继承SerializerMixin
class Base(DeclarativeBase, SerializerMixin):
pass
class Project(Base):
__tablename__="projects"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
owner_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
class User(Base):
__tablename__="users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
projects: Mapped[list[Project]] = relationship(backref="owner")
# 使用 serialize_rules 避免循环引用,例如在序列化项目时不再序列化项目的owner
serialize_rules = ('-projects.owner',)
# 数据库初始化与会话管理
engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
session_maker = sessionmaker(bind=engine)
with session_maker() as session:
user = User(name="User1")
user.projects.append(Project(name="Project 1"))
user.projects.append(Project(name="Project 2"))
session.add(user)
session.commit()
session.refresh(user) # 刷新对象以加载关联数据
# 序列化为字典并转换为JSON字符串
print(json.dumps(user.to_dict(), indent=4))输出示例
{
"id": 1,
"projects": [
{
"id": 1,
"name": "Project 1",
"owner_id": 1
},
{
"id": 2,
"name": "Project 2",
"owner_id": 1
}
],
"name": "User1"
}注意事项
- serialize_rules 是一个强大的工具,可以精细控制序列化过程。例如,('name', 'email', '-password') 表示只包含 name 和 email 字段,并排除 password 字段。
- 对于复杂的关联关系,合理设置 serialize_rules 至关重要,以防止性能问题和无限递归。
方案二:结合 Pydantic 进行数据验证与序列化
Pydantic 是一个基于类型提示的Python数据验证和设置管理库。它不仅能用于验证输入数据,还能作为强大的序列化工具,将复杂的Python对象(包括SQLAlchemy模型)转换为标准化的字典或JSON。
实现步骤
- 安装:
pip install pydantic sqlalchemy
- 定义 Pydantic 模型: 为每个需要序列化的 SQLAlchemy 模型创建对应的 Pydantic 模型。
- 配置 ConfigDict: 在 Pydantic 模型中设置 model_config = ConfigDict(from_attributes=True) (Pydantic v2+),这告诉 Pydantic 它可以从ORM对象(如SQLAlchemy模型)的属性中读取数据。在Pydantic v1中,对应的是 Config.orm_mode = True。
- 序列化: 使用 Pydantic 模型的 model_validate() 方法(Pydantic v2+)或 from_orm() 方法(Pydantic v1)从 SQLAlchemy 实例创建 Pydantic 实例,然后调用 model_dump_json() 或 json() 进行序列化。
示例代码
from sqlalchemy import ForeignKey, create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, sessionmaker
from pydantic import BaseModel, ConfigDict
# SQLAlchemy 模型定义
class Base(DeclarativeBase):
pass
class Project(Base):
__tablename__="projects"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
owner_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
class User(Base):
__tablename__="users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
projects: Mapped[list[Project]] = relationship(backref="owner")
# Pydantic 模型定义
class ProjectScheme(BaseModel):
# 启用从ORM对象读取属性
model_config = ConfigDict(from_attributes=True)
id: int
name: str
class UserScheme(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
name: str
projects: list[ProjectScheme] # 关联字段也需要对应的Pydantic模型
# 数据库初始化与会话管理
engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
session_maker = sessionmaker(bind=engine)
with session_maker() as session:
user = User(name="User1")
user.projects.append(Project(name="Project 1"))
user.projects.append(Project(name="Project 2"))
session.add(user)
session.commit()
session.refresh(user)
# 通过Pydantic模型验证并序列化SQLAlchemy对象
user_json = UserScheme.model_validate(user).model_dump_json(indent=4)
print(user_json)输出示例
{
"id": 1,
"name": "User1",
"projects": [
{
"id": 1,
"name": "Project 1"
},
{
"id": 2,
"name": "Project 2"
}
]
}注意事项
- Pydantic 提供了清晰的数据结构定义,有助于API文档生成和前后端接口一致性。
- 需要为每个 SQLAlchemy 模型手动创建对应的 Pydantic 模型,这可能增加一些重复代码,但在大型项目中,这种显式定义有助于维护。
- Pydantic 默认不处理循环引用,需要手动调整 Pydantic 模型结构来避免。
方案三:使用 SQLModel (整合 SQLAlchemy 和 Pydantic)
SQLModel 是一个由 FastAPI 作者开发的库,它旨在简化数据库交互,通过将 SQLAlchemy 和 Pydantic 的优势结合起来,允许你用一个模型定义同时作为数据库表和数据验证/序列化模型。
实现步骤
- 安装:
pip install sqlmodel
- 定义 SQLModel: 模型直接继承 SQLModel,并使用 Field 和 Relationship 来定义字段和关系。table=True 参数表示这是一个数据库表。
- 定义输出模型: 可以定义一个独立的 Pydantic 模型(继承 SQLModel 或 BaseModel)作为输出模型,以控制序列化时包含的字段。
- 序列化: 直接使用 SQLModel 实例的 model_dump_json() 方法。
示例代码
from typing import Optional
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlmodel import SQLModel, Field, Relationship
# 定义项目基础模型
class ProjectBase(SQLModel):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
# 定义项目数据库模型
class Project(ProjectBase, table=True):
__tablename__="projects"
owner_id: Optional[int] = Field(default=None, foreign_key="users.id")
owner: "User" = Relationship(back_populates="projects") # 定义反向关系
# 定义用户基础模型
class UserBase(SQLModel):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
# 定义用户数据库模型
class User(UserBase, table=True):
__tablename__="users"
projects: list[Project] = Relationship(back_populates="owner") # 定义关联关系
# 定义用户输出模型 (用于序列化,可以控制输出字段)
class UserOutput(UserBase):
projects: list[ProjectBase] = [] # 关联字段使用ProjectBase以避免循环或精简输出
# 数据库初始化与会话管理
engine = create_engine("sqlite://")
SQLModel.metadata.create_all(engine)
session_maker = sessionmaker(bind=engine)
with session_maker() as session:
user = User(name="User1")
user.projects.append(Project(name="Project 1"))
user.projects.append(Project(name="Project 2"))
session.add(user)
session.commit()
session.refresh(user)
# 通过输出模型验证并序列化SQLModel对象
print(UserOutput.model_validate(user).model_dump_json(indent=4))输出示例
{
"id": 1,
"name": "User1",
"projects": [
{
"id": 1,
"name": "Project 1"
},
{
"id": 2,
"name": "Project 2"
}
]
}注意事项
- SQLModel 大幅减少了模型定义的冗余,一个模型同时承担了数据库表定义和数据验证/序列化的职责。
- 它天生支持异步操作,与 FastAPI 配合默契。
- 对于需要高度定制化序列化逻辑的场景,可能需要结合 Pydantic 的高级特性或手动调整输出模型。
总结与建议
选择哪种序列化方案取决于你的项目需求和偏好:
- SQLAlchemy-serializer: 如果你希望快速为现有 SQLAlchemy 项目添加序列化功能,且不希望引入额外的 Pydantic 模型定义,SQLAlchemy-serializer 是一个轻量且方便的选择。它提供了灵活的规则控制来处理复杂的关联和循环引用。
- Pydantic: 如果你的项目需要严格的数据验证、清晰的API文档,并且已经在使用或计划使用Pydantic进行请求体验证,那么将其扩展到 SQLAlchemy 模型的序列化是非常自然且推荐的做法。它提供了类型安全和强大的验证能力。
- SQLModel: 如果你正在启动一个新项目,特别是与 FastAPI 结合使用,SQLModel 是一个极佳的选择。它通过统一模型定义,显著减少了开发冗余,并提供了 Pydantic 的所有优势。
无论选择哪种方案,都应注意:
- 性能: 对于大规模数据,考虑查询时只加载必要的字段(使用 session.query(Model.field1, Model.field2)),或使用ORM提供的延迟加载策略。
- 循环引用: 在处理复杂关系时,务必注意避免无限递归,合理配置序列化规则或 Pydantic/SQLModel 的输出模型。
- 数据安全: 在序列化前,确保敏感信息(如密码哈希)已被排除。
通过上述方法,你可以有效地将复杂的 SQLAlchemy 模型转换为结构良好、易于消化的 JSON 格式,从而构建健壮且高效的后端API。
今天带大家了解了的相关知识,希望对你有所帮助;关于文章的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
花呗怎么用?开通教程详解
- 上一篇
- 花呗怎么用?开通教程详解
- 下一篇
- 小红书千帆商品发布教程与上架指南
-
- 文章 · python教程 | 6小时前 |
- Python如何重命名数据列名?columns教程
- 165浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- 异步Python机器人如何非阻塞运行?
- 216浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- Python排序忽略大小写技巧详解
- 325浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- Python列表引用与复制技巧
- 300浏览 收藏
-
- 文章 · python教程 | 8小时前 | 数据处理 流处理 PythonAPI PyFlink ApacheFlink
- PyFlink是什么?Python与Flink结合解析
- 385浏览 收藏
-
- 文章 · python教程 | 9小时前 | sdk 邮件API requests库 smtplib Python邮件发送
- Python发送邮件API调用方法详解
- 165浏览 收藏
-
- 文章 · python教程 | 9小时前 |
- Pandasmerge_asof快速匹配最近时间数据
- 254浏览 收藏
-
- 文章 · python教程 | 9小时前 |
- 列表推导式与生成器表达式区别解析
- 427浏览 收藏
-
- 文章 · python教程 | 9小时前 |
- Pythonopen函数使用技巧详解
- 149浏览 收藏
-
- 文章 · python教程 | 9小时前 |
- Python合并多个列表的几种方法
- 190浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3193次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3405次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3436次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4543次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3814次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

