
在现代web服务开发中,将后端数据库中的数据模型转换为前端可理解的json格式是常见的需求。当使用sqlalchemy作为orm时,直接将sqlalchemy模型对象序列化为json并非总是直观,尤其当模型包含复杂的关系(如一对多、多对多)或继承结构时。一个简单的将模型属性转换为字典的方法,例如遍历__table__.columns,往往只能获取模型直接拥有的列,而无法包含关联对象或继承而来的属性,这在构建功能完善的api时会遇到障碍。为了解决这一问题,本文将介绍三种专业且高效的sqlalchemy模型json序列化策略。
SQLAlchemy-serializer是一个为SQLAlchemy模型提供序列化功能的mixin类,它允许开发者轻松地将模型对象转换为字典或JSON字符串,并能灵活控制关联对象的序列化深度,有效避免循环引用问题。
以下示例展示了如何使用SQLAlchemy-serializer将包含一对多关系的用户和项目模型序列化为JSON。
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")
# 序列化规则:停止对projects关联的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())){"id": 1, "projects": [{"id": 1, "name": "Project 1", "owner_id": 1}, {"id": 2, "name": "Project 2", "owner_id": 1}], "name": "User1"}输出清晰地展示了用户及其关联的项目列表,serialize_rules成功阻止了projects中再次包含owner信息,避免了无限递归。
Pydantic是一个强大的数据验证和设置管理库,它使用Python类型注解来定义数据模型,并提供运行时类型检查。结合Pydantic可以为API响应提供严格的结构定义和数据校验,同时实现SQLAlchemy模型的序列化。
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
# SQLAlchemy模型定义
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模型定义(用于API输出)
class ProjectScheme(BaseModel):
# 允许从任意对象属性读取数据
model_config = ConfigDict(from_attributes=True)
id: int
name: str
class UserScheme(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
name: str
# 嵌套Pydantic模型以处理关系
projects: list[ProjectScheme]
# 数据库初始化与会话创建
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()
print(user_json){"id":1,"name":"User1","projects":[{"name":"Project 1","id":1},{"name":"Project 2","id":2}]}Pydantic模型成功将SQLAlchemy对象转换为JSON,并严格遵循了UserScheme和ProjectScheme中定义的结构。
SQLModel是一个由FastAPI的作者开发的库,它结合了SQLAlchemy和Pydantic的优点,允许开发者使用单一的模型定义来同时处理数据库操作和数据验证/序列化。
from typing import Optional
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlmodel import SQLModel, Field, Relationship
# 定义项目基础模型(Pydantic部分)
class ProjectBase(SQLModel):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
# 定义项目数据库模型(SQLAlchemy部分,继承ProjectBase)
class Project(ProjectBase, table=True):
__tablename__ = "projects"
owner_id: Optional[int] = Field(default=None, foreign_key="users.id")
# 定义与User的关系
owner: "User" = Relationship(back_populates="projects")
# 定义用户基础模型(Pydantic部分)
class UserBase(SQLModel):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
# 定义用户数据库模型(SQLAlchemy部分,继承UserBase)
class User(UserBase, table=True):
__tablename__ = "users"
# 定义与Project的关系
projects: list[Project] = Relationship(back_populates="owner")
# 定义用户输出模型(Pydantic部分,用于API响应,只包含需要输出的字段和关系)
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)
# 使用UserOutput模型验证并序列化SQLModel对象
print(UserOutput.model_validate(user).model_dump_json()){"id":1,"name":"User1","projects":[{"name":"Project 1","id":1},{"name":"Project 2","id":2}]}SQLModel通过UserOutput模型,成功地将User对象序列化为JSON,同时处理了嵌套的Project对象。
将SQLAlchemy模型序列化为JSON是API开发中的核心环节。选择哪种策略取决于项目的具体需求、团队熟悉度以及对灵活性和严格性的偏好。
SQLAlchemy-serializer:
Pydantic:
SQLModel:
在实际开发中,开发者可以根据项目的规模、对数据校验的需求、以及团队对不同工具的熟悉程度来做出最佳选择。无论选择哪种方法,理解其工作原理和适用场景都将有助于构建出高效、健壮的API服务。
以上就是将SQLAlchemy模型高效转换为JSON:API序列化策略深度解析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号