SQLAlchemy作为Python生态中主流的ORM框架,被广泛用于数据库交互场景,在实际开发中经常需要将查询得到的模型实例转换为JSON格式返回给前端。不同的转换方案在易用性、性能和扩展性上存在明显差异,下面逐一解析。

基础方案:手动提取字段
最简单的方式是手动从模型实例中提取需要的字段,组装成字典后再通过json模块序列化。这种方式适合字段少、无关联关系的简单模型。
import json
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
# 创建模拟实例
user = User(id=1, name='张三', age=25)
# 手动提取字段转字典
user_dict = {
'id': user.id,
'name': user.name,
'age': user.age
}
# 转换为JSON
json_result = json.dumps(user_dict, ensure_ascii=False)
print(json_result)
这种方式的优点是逻辑直观、没有额外依赖,缺点是字段较多时需要重复写大量提取代码,模型新增字段时还要同步修改转换逻辑,维护成本高。
进阶方案:模型添加序列化方法
可以在模型类中定义通用的序列化方法,自动提取所有字段,减少重复代码。通过模型的__table__.columns属性可以获取所有定义的列字段。
import json
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
create_time = Column(DateTime)
def to_dict(self):
# 遍历所有列字段,提取字段名和对应值
result = {}
for column in self.__table__.columns:
value = getattr(self, column.name)
# 处理时间类型字段,转换为字符串
if hasattr(value, 'strftime'):
value = value.strftime('%Y-%m-%d %H:%M:%S')
result[column.name] = value
return result
# 模拟实例
user = User(id=1, name='李四', age=30, create_time=None)
# 调用方法转字典再序列化
user_dict = user.to_dict()
json_result = json.dumps(user_dict, ensure_ascii=False)
print(json_result)
该方案实现了字段的自动提取,新增字段时不需要修改序列化逻辑,但是无法直接处理模型之间的关联关系,比如用户关联的文章列表就无法自动序列化。
处理关联关系的方案:递归序列化
当模型存在外键关联时,需要在序列化方法中加入关联对象的处理逻辑,通过递归调用实现嵌套序列化。需要注意避免循环引用导致的无限递归问题。
import json
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
# 关联文章,一对多关系
posts = relationship('Post', back_populates='author')
def to_dict(self, depth=1):
if depth <= 0:
return {'id': self.id}
result = {}
for column in self.__table__.columns:
result[column.name] = getattr(self, column.name)
# 处理关联的文章列表
if self.posts:
result['posts'] = [post.to_dict(depth-1) for post in self.posts]
return result
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
title = Column(String(100))
user_id = Column(Integer, ForeignKey('users.id'))
author = relationship('User', back_populates='posts')
def to_dict(self, depth=1):
if depth <= 0:
return {'id': self.id}
result = {}
for column in self.__table__.columns:
result[column.name] = getattr(self, column.name)
if self.author:
result['author'] = self.author.to_dict(depth-1)
return result
# 模拟数据
user = User(id=1, name='王五')
post1 = Post(id=1, title='第一篇文章', author=user)
post2 = Post(id=2, title='第二篇文章', author=user)
user.posts = [post1, post2]
json_result = json.dumps(user.to_dict(), ensure_ascii=False)
print(json_result)
通过深度参数控制递归层级,可以避免循环引用问题,但是递归逻辑编写复杂度较高,嵌套层级较深时性能也会有所下降。
第三方库方案:使用marshmallow
marshmallow是Python中常用的序列化/反序列化库,可以和SQLAlchemy很好地结合,支持字段校验、自定义字段序列化规则,扩展性更强。
import json
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from marshmallow import Schema, fields
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
age = Column(Integer)
# 定义序列化Schema
class UserSchema(Schema):
id = fields.Integer()
name = fields.String()
age = fields.Integer()
# 初始化Schema
user_schema = UserSchema()
# 模拟实例
user = User(id=2, name='赵六', age=28)
# 单个实例序列化
result = user_schema.dump(user)
json_result = json.dumps(result, ensure_ascii=False)
print(json_result)
# 多个实例序列化
users = [User(id=3, name='钱七', age=22), User(id=4, name='孙八', age=35)]
results = user_schema.dump(users, many=True)
json_results = json.dumps(results, ensure_ascii=False)
print(json_results)
marshmallow的优势在于可以灵活定义字段规则,比如字段别名、默认值、是否排除某些字段,还支持嵌套Schema处理关联关系,适合中大型项目的复杂序列化需求,缺点是引入了额外的第三方依赖。
方案对比与选择建议
不同方案的适用场景如下:
- 手动提取字段:适合字段极少、无关联关系的临时调试场景,不推荐用于正式项目
- 模型添加序列化方法:适合字段固定、无复杂关联关系的中小型项目,开发成本低
- 递归序列化:适合有关联关系、不想引入第三方库的项目,但是维护成本较高
- marshmallow方案:适合中大型项目、序列化规则复杂、需要字段校验的场景,扩展性最好
开发者可以根据项目的规模、关联关系复杂度和后续扩展需求选择合适的转换方案,在开发效率和可维护性之间找到平衡。
SQLAlchemyJSON转换ORM模型Python序列化修改时间:2026-06-15 17:24:45