SQLAlchemy Model Object to json 对象转 JSON

本文介绍了如何将SQLAlchemy ORM对象转换为JSON格式的方法。包括单个对象和对象列表的序列化过程,并提供了具体的代码实现及使用示例。

将SQLAlchemy Model Object 转成 JSON

from sqlalchemy.orm import class_mapper

def serialize(model):
  """Transforms a model into a dictionary which can be dumped to JSON."""
  # first we get the names of all the columns on your model
  columns = [c.key for c in class_mapper(model.__class__).columns]
  # then we return their values in a dict
  return dict((c, getattr(model, c)) for c in columns)

将对象传入就会返回一个 dict 类型的数据,再将它转成 json 就可以了。

使用方法

d=serialize(SQLAlchemyModelobject)
jsondumps(d)

思路来源 http://stackoverflow.com/questions/10252010/serializing-python-object-instance-to-json

 

Qurey 查询后的结果变成 JSON

单个对象

def to_json(model):
    """ Returns a JSON representation of an SQLAlchemy-backed object. """
    json = {}
    # json['fields'] = {}
    # json['pk'] = getattr(model, 'id')
    for col in model._sa_class_manager.mapper.mapped_table.columns:
        # json['fields'][col.name] = getattr(model, col.name)
        json[col.name] = getattr(model, col.name)
    # return dumps([json])
    return json

一组对象


def to_json_list(model_list):
    json_list = []
    for model in model_list:
        json_list.append(to_json(model))
    return json_list

使用演示

#读取一个资源
    def get(self,id):
        session = common.db.getDBSession()
        appkey=session.query(AppKey).filter_by(id=id).first()
        session.close()
        result= common.util.to_json(appkey)
        return result

    #获取全部资源
    def get(self):
        session =common.db.getDBSession()
        appkeylist =session.query(AppKey).all()
        session.close()
        result = common.util.to_json_list(appkeylist)
        return result

 

转载于:https://my.oschina.net/caomenglong/blog/715806

在使用 SQLAlchemy 时,将数据库查询结果换为 JSON 是一个常见的需求(尤其是在构建 REST API 时)。但由于 **SQLAlchemy 模型对象不是直接可序列化的**(即不能直接 `json.dumps(instance)`),你需要先将其换为字典结构。 --- ## ✅ 目标 将 SQLAlchemy 查询出的模型实例(如 `User`)安全、正确地Python 字典,并最终通过 `json.dumps()` 输出 JSON 字符串。 --- ## 🛠 解决方案概览 | 方法 | 说明 | |------|------| | 1️⃣ 手动定义 `.dict()` 或 `to_dict()` 方法 | 简单可控,适合小项目 | | 2️⃣ 使用 `sqlalchemy.orm.class_mapper` 提取列 | 动态获取字段,通用性强 | | 3️⃣ 使用 Pydantic(推荐 + FastAPI 集成) | 最佳实践,自动校验 + 序列化 | | 4️⃣ 使用 `__dict__`(谨慎) | 快速但可能包含非字段属性或循环引用 | --- ## ✅ 方案一:自定义 `to_dict()` 方法(简单明了) ```python from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base import json Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) account = Column(String(100), nullable=False) password = Column(String(255), nullable=False) # ⚠️ 实际应加密存储 def to_dict(self): return { "id": self.id, "account": self.account # 不返回 password! } def to_json(self): return json.dumps(self.to_dict(), ensure_ascii=False, indent=2) ``` ### 使用示例: ```python user = session.query(User).first() print(user.to_json()) ``` 输出: ```json { "id": 1, "account": "alice" } ``` > ✅ 优点:控制精细,可排除敏感字段 > ❌ 缺点:每个模型都要手动写 --- ## ✅ 方案二:动态提取所有列(通用函数) 利用 SQLAlchemy 的 `class_mapper` 获取模型的所有列名,动态生成字典: ```python from sqlalchemy.orm import class_mapper def model_to_dict(model): if not model: return None mapper = class_mapper(model.__class__) columns = [col.key for col in mapper.columns] return {c: getattr(model, c) for c in columns} # JSON def model_to_json(model): return json.dumps(model_to_dict(model), default=str, ensure_ascii=False, indent=2) ``` ### 使用示例: ```python user = session.query(User).first() print(model_to_json(user)) ``` > ✅ 优点:适用于任意模型 > ⚠️ 注意:仍会暴露 `password` 字段,需额外过滤 #### 🔐 安全增强版(排除特定字段): ```python def model_to_dict(model, exclude=None): exclude = exclude or set() mapper = class_mapper(model.__class__) columns = [col.key for col in mapper.columns if col.key not in exclude] return {c: getattr(model, c) for c in columns} # 示例:排除密码 data = model_to_dict(user, exclude={"password"}) ``` --- ## ✅ 方案三:使用 Pydantic(强烈推荐,尤其配合 FastAPI) 这是现代 Python Web 开发中的 **最佳实践**。 ### 步骤 1:定义 Pydantic 模型(Schema) ```python from pydantic import BaseModel from typing import Optional class UserOut(BaseModel): id: int account: str class Config: from_attributes = True # 允许从 ORM 模型加载数据(旧版叫 orm_mode) ``` > ⚠️ `from_attributes=True` 表示允许从 SQLAlchemy 对象中读取属性。 ### 步骤 2:查询并换 ```python user = session.query(User).first() user_data = UserOut.model_validate(user) # 换为 Pydantic 模型 json_str = user_data.model_dump_json(indent=2) print(json_str) ``` 输出: ```json { "id": 1, "account": "alice" } ``` ### ✅ 优势: - 自动类型验证; - 可控字段输出(不包含 `password`); - 支持嵌套模型(如 `user.info`); - 与 FastAPI 原生集成,返回即可自动 JSON; #### FastAPI 示例: ```python @app.get("/user/{user_id}", response_model=UserOut) def get_user(user_id: int): user = session.query(User).get(user_id) return user # FastAPI 自动调用 model_validate 并输出 JSON ``` --- ## ✅ 方案四:处理关系(一对多、外键等) 假设你有: ```python class User_Info(Base): __tablename__ = "user_info" Stu_ID = Column(String(100), primary_key=True) name = Column(String(100)) user_id = Column(Integer, ForeignKey("users.id")) user = relationship("User", back_populates="info") User.info = relationship("User_Info", uselist=False, back_populates="user") ``` 你可以扩展 `to_dict` 支持嵌套: ```python def model_to_dict(model, recurse=True, exclude=None): exclude = exclude or set() mapper = class_mapper(model.__class__) cols = [col.key for col in mapper.columns if col.key not in exclude] result = {c: getattr(model, c) for c in cols} if recurse: for rel in mapper.relationships: value = getattr(model, rel.key) if value is None: result[rel.key] = None elif rel.uselist: result[rel.key] = [model_to_dict(item, recurse=True, exclude=exclude) for item in value] else: result[rel.key] = model_to_dict(value, recurse=True, exclude=exclude) return result ``` 这样就能输出带关联信息的 JSON: ```json { "id": 1, "account": "alice", "info": { "Stu_ID": "20210001", "name": "Alice Zhang" } } ``` --- ## ⚠️ 常见问题与注意事项 | 问题 | 解决方案 | |------|----------| | `Object of type datetime is not JSON serializable` | 使用 `default=str` 或自定义 encoder | | 包含循环引用(A→B→A)导致栈溢出 | 控制递归深度或移除反向关系输出 | | 密码等敏感字段泄露 | 显式排除字段(如不加入 dict) | | Lazy loading 触发数据库查询 | 使用 `joinedload` 预加载,或确保序列化时已加载 | ### 自定义 JSON Encoder(解决日期等问题) ```python import json from datetime import datetime, date class CustomJSONEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (datetime, date)): return obj.isoformat() return super().default(obj) json.dumps(data, cls=CustomJSONEncoder) ``` --- ## ✅ 总结对比 | 方法 | 是否推荐 | 适用场景 | |------|---------|----------| | `to_dict()` 手动写 | ✅ 推荐小项目 | 简单、安全、可控 | | 动态提取列 | ✅ 中大型项目 | 通用工具函数 | | Pydantic 模型 | ✅✅✅ 强烈推荐 | FastAPI、微服务、前后端分离 | | 直接 `dict(model)` 或 `__dict__` | ❌ 不推荐 | 可能漏数据或出错 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值