Marshmallow是Python生态中用于对象序列化与反序列化的常用库,在处理数据库模型、API数据交互等场景时,经常需要将多个关联的模型字段整合成嵌套的JSON结构,而不是扁平的字段集合,这样能更贴合前端的数据使用习惯,也能清晰体现数据之间的关联关系。

Marshmallow基础序列化回顾
在使用嵌套结构之前,先了解Marshmallow的基础序列化逻辑。首先需要定义一个继承自Schema的类,在类中声明需要序列化的字段,然后将模型实例传入Schema的dump方法即可完成序列化。
比如我们有一个简单的用户模型,包含用户id、用户名两个基础字段,对应的基础序列化Schema如下:
from marshmallow import Schema, fields
# 模拟用户模型
class User:
def __init__(self, user_id, username):
self.user_id = user_id
self.username = username
# 用户基础序列化Schema
class UserSchema(Schema):
user_id = fields.Integer()
username = fields.String()
# 使用Schema序列化
user = User(user_id=1, username="张三")
user_schema = UserSchema()
result = user_schema.dump(user)
print(result) # 输出:{'user_id': 1, 'username': '张三'}
嵌套结构的核心实现方式
Marshmallow中实现嵌套结构的核心是fields.Nested字段,这个字段可以接收一个其他的Schema类,将对应Schema序列化得到的结果作为当前字段的值,从而实现字段的嵌套包装。
一对一嵌套场景
一对一嵌套是最常见的场景,比如用户和用户的详细信息是一对一的关系,用户详细信息包含年龄、手机号两个字段,我们希望序列化用户的时候,把详细信息作为用户的一个嵌套字段返回。
首先定义用户详细信息的Schema和用户模型:
from marshmallow import Schema, fields
# 模拟用户详细信息模型
class UserProfile:
def __init__(self, age, phone):
self.age = age
self.phone = phone
# 模拟用户模型,包含用户基本信息和关联的详细信息
class User:
def __init__(self, user_id, username, profile):
self.user_id = user_id
self.username = username
self.profile = profile
# 用户详细信息Schema
class UserProfileSchema(Schema):
age = fields.Integer()
phone = fields.String()
# 用户Schema,使用Nested字段嵌套UserProfileSchema
class UserSchema(Schema):
user_id = fields.Integer()
username = fields.String()
# 嵌套字段,值为UserProfileSchema的实例
profile = fields.Nested(UserProfileSchema)
接下来测试序列化效果:
# 创建关联数据
profile = UserProfile(age=25, phone="13800138000")
user = User(user_id=1, username="张三", profile=profile)
user_schema = UserSchema()
result = user_schema.dump(user)
print(result)
# 输出:{'user_id': 1, 'username': '张三', 'profile': {'age': 25, 'phone': '13800138000'}}
一对多嵌套场景
一对多嵌套指的是一个主模型关联多个子模型,比如一个作者可以写多篇文章,我们希望序列化作者的时候,把所有文章的信息作为嵌套的列表字段返回。
实现方式和一对一类似,只需要在fields.Nested中添加many=True参数,表示这个字段对应的是多个子对象组成的列表。
from marshmallow import Schema, fields
# 模拟文章模型
class Article:
def __init__(self, article_id, title, content):
self.article_id = article_id
self.title = title
self.content = content
# 模拟作者模型,关联多篇文章
class Author:
def __init__(self, author_id, name, articles):
self.author_id = author_id
self.name = name
self.articles = articles
# 文章Schema
class ArticleSchema(Schema):
article_id = fields.Integer()
title = fields.String()
content = fields.String()
# 作者Schema,嵌套文章列表
class AuthorSchema(Schema):
author_id = fields.Integer()
name = fields.String()
# many=True表示articles是多个Article对象的列表
articles = fields.Nested(ArticleSchema, many=True)
测试一对多嵌套的序列化效果:
# 创建文章数据
article1 = Article(article_id=1, title="Python基础", content="Python入门教程")
article2 = Article(article_id=2, title="Marshmallow教程", content="Marshmallow使用指南")
# 创建作者数据,关联两篇文章
author = Author(author_id=1, name="李四", articles=[article1, article2])
author_schema = AuthorSchema()
result = author_schema.dump(author)
print(result)
# 输出:{'author_id': 1, 'name': '李四', 'articles': [{'article_id': 1, 'title': 'Python基础', 'content': 'Python入门教程'}, {'article_id': 2, 'title': 'Marshmallow教程', 'content': 'Marshmallow使用指南'}]}
嵌套序列化的注意事项
- 嵌套的Schema可以复用,比如多个不同的父Schema都可以嵌套同一个子Schema,不需要重复定义字段。
- 如果嵌套的模型中某个字段不需要序列化,可以在子Schema中不包含该字段,Marshmallow会自动忽略模型中不存在于Schema的字段。
- 如果嵌套层级过深,需要注意避免出现循环引用的问题,比如A嵌套B,B又嵌套A,这种情况下Marshmallow会抛出递归错误,需要合理设计嵌套层级。
- 可以通过给
fields.Nested传递dump_only=True参数,设置该嵌套字段只在序列化时生效,反序列化时忽略。
常见使用场景
嵌套序列化在API开发中使用非常广泛,比如电商系统中,订单模型可以嵌套商品列表、收货地址等子结构;博客系统中,评论模型可以嵌套评论用户的基础信息,不需要把用户的全部字段都返回,既减少了数据传输量,也让数据结构更清晰。
通过fields.Nested字段,Marshmallow可以灵活实现各种复杂的嵌套结构需求,开发者只需要根据数据关联关系定义好对应的Schema,就能快速完成模型字段的嵌套序列化工作。
Marshmallow序列化嵌套结构模型字段修改时间:2026-07-20 13:57:34