Marshmallow简介

Marshmallow是一个强大的Python库,用于简化复杂数据类型与Python原生数据类型之间的转换过程。它提供了一种简单、灵活的方式来:

🔄

序列化

将复杂数据类型(如ORM对象)转换为Python原生数据类型,以便转换为JSON等格式

🔙

反序列化

将Python原生数据类型(如来自JSON请求的数据)转换为复杂数据类型

数据验证

在反序列化过程中验证输入数据是否符合预期格式和约束

为什么选择Marshmallow? Marshmallow特别适合在Web API开发中使用,能够简化请求和响应数据的处理流程。它与Flask、Django等Web框架完美集成,是处理JSON数据的理想选择。

安装与配置

使用pip安装Marshmallow非常简单:

命令行
pip install marshmallow

安装完成后,你可以在Python文件中导入并使用它:

Python代码
from marshmallow import Schema, fields

注意: Marshmallow需要Python 3.7或更高版本。建议在虚拟环境中安装以保持项目依赖的隔离。

定义Schema

Schema是Marshmallow的核心概念,它定义了数据序列化和反序列化的规则。每个Schema类对应一种数据类型。

定义User Schema
from marshmallow import Schema, fields, validate

class UserSchema(Schema):
    id = fields.Int(dump_only=True)  # 只用于序列化输出
    name = fields.Str(required=True)
    email = fields.Email(required=True)
    age = fields.Int(
        required=True,
        validate=validate.Range(min=18, max=120, error="年龄必须在18-120岁之间")
    )
    created_at = fields.DateTime(dump_only=True)
    is_active = fields.Boolean(missing=True)  # 默认值

字段类型

  • String (Str)
  • Integer (Int)
  • Boolean (Boolean)
  • DateTime
  • Email
  • List (List)
  • Nested (嵌套Schema)

常用参数

  • required: 字段是否必需
  • validate: 验证器函数
  • dump_only: 只用于序列化输出
  • load_only: 只用于反序列化输入
  • missing: 默认值
  • error_messages: 自定义错误消息

数据序列化

序列化是将复杂数据类型(如ORM对象)转换为简单数据类型(如字典、JSON)的过程。

序列化示例
from datetime import datetime

# 创建一个用户对象
user = {
    "id": 1,
    "name": "张三",
    "email": "zhangsan@example.com",
    "age": 28,
    "created_at": datetime.now(),
    "is_active": True
}

# 序列化单个对象
schema = UserSchema()
result = schema.dump(user)
print(result)
# 输出: {'name': '张三', 'email': 'zhangsan@example.com', ...}

# 序列化为JSON
json_result = schema.dumps(user)
print(json_result)

提示: 使用dump_only=True的字段(如id和created_at)在序列化时会包含在输出中,但在反序列化时会被忽略。

数据反序列化

反序列化是将简单数据类型(如JSON)转换为复杂数据类型的过程,通常用于处理客户端提交的数据。

反序列化示例
# 用户提交的数据(通常来自JSON请求)
user_data = {
    "name": "李四",
    "email": "lisi@example.com",
    "age": 25
}

# 反序列化数据
schema = UserSchema()
result = schema.load(user_data)
print(result)  # 输出: {'name': '李四', 'email': 'lisi@example.com', 'age': 25, 'is_active': True}

# 从JSON字符串反序列化
json_data = '{"name": "王五", "email": "wangwu@example.com", "age": 30}'
result = schema.loads(json_data)

注意: 反序列化时会自动应用字段验证。如果数据无效,Marshmallow会抛出ValidationError异常。

数据验证

Marshmallow提供了强大的数据验证功能,确保输入数据符合预期格式和业务规则。

验证示例
from marshmallow import ValidationError

# 无效的用户数据
invalid_data = {
    "name": "赵六",
    "email": "invalid-email",  # 无效的邮箱格式
    "age": 15  # 低于最小年龄
}

try:
    result = schema.load(invalid_data)
except ValidationError as err:
    print(err.messages)
    # 输出: 
    # {
    #   'email': ['Not a valid email address.'],
    #   'age': ['年龄必须在18-120岁之间']
    # }

内置验证器

  • validate.Range: 数值范围验证
  • validate.Length: 长度验证
  • validate.OneOf: 值在预定义列表中
  • validate.Regexp: 正则表达式验证
  • validate.URL: URL格式验证
  • validate.Email: 邮箱格式验证

嵌套Schema

对于复杂的数据结构,可以使用嵌套Schema来处理关联数据。

嵌套Schema示例
class AddressSchema(Schema):
    street = fields.Str(required=True)
    city = fields.Str(required=True)
    country = fields.Str(required=True)

class UserWithAddressSchema(Schema):
    id = fields.Int(dump_only=True)
    name = fields.Str(required=True)
    email = fields.Email(required=True)
    address = fields.Nested(AddressSchema)  # 嵌套地址Schema
    
# 使用示例
user_data = {
    "name": "钱七",
    "email": "qianqi@example.com",
    "address": {
        "street": "人民路123号",
        "city": "上海市",
        "country": "中国"
    }
}

schema = UserWithAddressSchema()
result = schema.load(user_data)

提示: 使用many=True参数可以处理对象列表,这在处理多个嵌套对象时非常有用。