如何用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)
方案细节说明
- 原生特性完全保留:在
AttributesSchema里可以正常使用fields.Integer(as_string=True)这类内置转换、验证逻辑,序列化时自动把整数attr1转成字符串格式,反序列化时也能自动把字符串转回整数,完全复用Marshmallow的原生能力。 - attribute参数的巧妙用法:
fields.Nested的attribute参数传入一个lambda,直接把当前的Thing对象传给AttributesSchema,这样嵌套Schema就能直接读取对象的attr1和attr2属性,不需要额外的字段映射。 - 正反序列化双向支持:这个方案同时支持序列化(模型转JSON)和反序列化(JSON转模型结构),验证规则也能完全复用嵌套Schema的配置。
对比钩子函数的优势
- 更符合Marshmallow的"声明式"设计思路,代码可读性更高,逻辑更清晰;
- 不需要手动处理字段的移动、转换,完全依赖框架原生机制,减少自定义代码的维护成本;
- 嵌套Schema可以单独复用,如果其他业务场景需要处理
attributes结构,直接引入AttributesSchema即可。
内容的提问来源于stack exchange,提问作者Umm
相关产品推荐
相关产品推荐

