Marshmallow 入门指南(Python 数据序列化与校验)
Marshmallow 是 Python 老牌序列化与校验库:Schema 定义、字段校验、错误处理、嵌套与数据转换。本文讲解 Marshmallow 的核心用法与 API 实战。
直接回答:Marshmallow 负责在复杂 Python 对象与简单数据类型之间双向转换(序列化/反序列化),并在入口把关数据校验——构建 API、处理表单、清洗管道数据都离不开它。 Schema 声明式定义,一次编写两用(进出都管)。
快速上手
pip install marshmallow
from marshmallow import Schema, fields, validate
class UserSchema(Schema):
name = fields.Str(required=True)
email = fields.Email(required=True)
age = fields.Int(validate=validate.Range(min=0, max=150))
created_at = fields.DateTime(dump_only=True) # 只输出,不接受输入
schema = UserSchema()
# 反序列化 + 校验(进来的数据)
user = schema.load({"name": "张三", "email": "zs@example.com", "age": 28})
# 序列化(出去的数据)
schema.dump(user) # -> {"name": "张三", ...}
load 管入(校验)、dump 管出(序列化)——dump_only/load_only(如密码字段)精确控制方向。
自定义校验
from marshmallow import validates, ValidationError
class UserSchema(Schema):
name = fields.Str(required=True)
password = fields.Str(load_only=True, required=True)
@validates("password")
def check_password(self, value, **kwargs):
if len(value) < 8:
raise ValidationError("密码至少 8 位")
多字段联合校验用 @validates_schema(如"两次密码一致")。
错误处理
校验失败抛 ValidationError,错误按字段组织:
def validate_user(data):
try:
user = schema.load(data)
except ValidationError as err:
return {"errors": err.messages}, 400
return user, 200
# {"errors": {"email": ["Not a valid email address."]}}
API 视图里把这个结构直接返回给前端——表单逐字段标红的数据就是它。
嵌套与转换
class AuthorSchema(Schema):
name = fields.Str()
class BookSchema(Schema):
title = fields.Str()
author = fields.Nested(AuthorSchema) # 嵌套对象
tags = fields.List(fields.Str()) # 列表
price = fields.Decimal(as_string=True) # Decimal 以字符串输出
数据整形三板斧:Nested 嵌套、Method 字段自定义计算、pre_load/post_dump 钩子在加载前后做转换(如兼容老格式字段名)。
实战中的位置
Marshmallow 不绑定任何框架:Flask-Marshmallow 提供框架集成,模型 Schema 自动生成还需 marshmallow-sqlalchemy;独立数据管道里它做 ETL 入口的清洗关卡;和 SQLAlchemy 组合(marshmallow-sqlalchemy)可以自动从表结构生成 Schema。
常见问题(FAQ)
Q:Marshmallow 和 Pydantic 怎么选?
A:Pydantic v2 使用 Rust 校验内核,性能需按数据与规则测量、类型注解风格更现代,FastAPI 生态默认它;Marshmallow 的 load/dump 双向语义与字段方向控制在"进出不对称"的场景更清晰,Flask 生态集成深。新项目无历史包袱偏 Pydantic,存量 Flask 继续 Marshmallow。
Q:性能敏感场景要注意什么?
A:序列化上万对象的循环里,先测量实际 Schema、钩子和数据形状的成本。可减少不必要的 Nested 层级,再用相同语义比较其他库,不预设性能排名。
Q:未知字段怎么处理?
A:Meta 里 公开资料未说明 = RAISE/EXCLUDE/INCLUDE 三选一。默认 RAISE 可暴露拼写或契约错误;EXCLUDE 会忽略未知输入,INCLUDE 保留未校验字段,应按安全与兼容要求显式选择。
官方参考
本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。