You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Marshmallow和SQLAlchemy将扁平Python对象转为嵌套JSON

问题描述

给定如下类SQLAlchemy风格的简单模型:

class Thing():
    name: str
    attr1: int
    attr2: str

如何编写对应的Marshmallow Schema类,生成如下格式的JSON?理想情况不使用fields.Method,这样才能用上fields.Integer(as_string=True)这类内置特性。

目标JSON格式:

{
 "name": "Name",
 "attributes": {
  "attr1": "1",
  "attr2": "attr2"
 }
}

我目前用了下面的写法,但希望找到不需要自定义方法的方案——手动转类型会浪费Marshmallow的特性,而且不确定反序列化的效果:

attributes = fields.Method("build_attributes")
def build_attributes(self, obj):
    return { "attr1": str(obj.attr1), "attr2": obj.attr2 }

补充:我还试过用@pre_load从数据里弹出字段并加到根节点(扁平化),用@post_dump创建根节点的attributes字段并把对应字段移进去(嵌套化),但这感觉不太符合Marshmallow的设计风格,不过它还能支持标准的Marshmallow验证。请问这是最佳方案吗?


最优解决方案:使用嵌套Schema

最贴合Marshmallow设计理念的方案是定义嵌套的AttributesSchema,直接映射模型的attr1和attr2字段,既能保留Marshmallow的字段特性,又不需要自定义方法或钩子函数。

具体实现代码:

from marshmallow import Schema, fields

class AttributesSchema(Schema):
    attr1 = fields.Integer(as_string=True)
    attr2 = fields.String()

class ThingSchema(Schema):
    name = fields.String()
    attributes = fields.Nested(AttributesSchema, attribute=lambda obj: obj)

方案细节说明

  1. 原生特性完全保留:在AttributesSchema里可以正常使用fields.Integer(as_string=True)这类内置转换、验证逻辑,序列化时自动把整数attr1转成字符串格式,反序列化时也能自动把字符串转回整数,完全复用Marshmallow的原生能力。
  2. attribute参数的巧妙用法:fields.Nested的attribute参数传入一个lambda,直接把当前的Thing对象传给AttributesSchema,这样嵌套Schema就能直接读取对象的attr1和attr2属性,不需要额外的字段映射。
  3. 正反序列化双向支持:这个方案同时支持序列化(模型转JSON)和反序列化(JSON转模型结构),验证规则也能完全复用嵌套Schema的配置。

对比钩子函数的优势

  • 更符合Marshmallow的"声明式"设计思路,代码可读性更高,逻辑更清晰;
  • 不需要手动处理字段的移动、转换,完全依赖框架原生机制,减少自定义代码的维护成本;
  • 嵌套Schema可以单独复用,如果其他业务场景需要处理attributes结构,直接引入AttributesSchema即可。

内容的提问来源于stack exchange,提问作者Umm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:22:48