0. 前言

  • Marshmallow 是一个用于将 ORM 对象与 Python 原生数据类型之间转换的库。实现 object → dict、object → list、string → dict 和 string → list 等功能

1. Schema

  • 实现一个 object 和 json 之间的转化需要一个 Schema 对象作为中间载体,同时实现校验的功能:
class ImageTpl(Schema):
value = fields.Dict(required=True, error_messages=get_field_valid_msg("图片模版值"))
height = fields.Int(required=True, error_messages=get_field_valid_msg("图片模版高度"))
width = fields.Int(required=True, error_messages=get_field_valid_msg("图片模版宽度"))

2. 序列化

  • 序列化使用 dump() 或者 dumps() 方法,其中 dump() 实现 object → dict,dumps() 实现 object → string:
from marshmallow import pprint

user = User(name="Monty", email="monty@python.org")
schema = UserSchema()
result = schema.dump(user)
pprint(result.data)
# {"name": "Monty",
# "email": "monty@python.org",
# "created_at": "2014-08-17T14:54:16.049594+00:00"}
  • 序列化的结果可以通过 only 参数指定字段:
from pprint import pprint

user_data = {
'created_at': '2014-08-11T05:26:03.869245',
'email': u'ken@yahoo.com',
'name': u'Ken'
}
schema = UserSchema()
result = schema.load(user_data)
pprint(result.data)
# {'name': 'Ken',
# 'email': 'ken@yahoo.com',
# 'created_at': datetime.datetime(2014, 8, 11, 5, 26, 3, 869245)},

3. 反序列化

  • 反序列化使用 load() 或者 loads() 方法,分别实现 dict → object 和 string → object。其中 dict → object 需要添加装饰器,自己实现逻辑:
from marshmallow import Schema, fields, post_load

class UserSchema(Schema):
name = fields.Str()
email = fields.Email()
created_at = fields.DateTime() @post_load
def make_user(self, data):
return User(**data) user_data = {
'name': 'Ronnie',
'email': 'ronnie@stones.com'
}
schema = UserSchema()
result = schema.load(user_data)
result.data # => <User(name='Ronnie')>

4. Field 对象

  • Schema 对象为每个属性赋值为一个 Field 对象设定转换类型的校验参数,具体如下:
  • validate 参数:指定一个 lambda 函数或者函数,定义校验逻辑,传入函数定义了 ValidationError 的话,返回信息会记录抛出的异常:
from marshmallow import Schema, fields, ValidationError

def validate_quantity(n):
if n < 0:
raise ValidationError('Quantity must be greater than 0.')
if n > 30:
raise ValidationError('Quantity must not be greater than 30.') class ItemSchema(Schema):
quantity = fields.Integer(validate=validate_quantity) in_data = {'quantity': 31}
result, errors = ItemSchema().load(in_data)
errors # => {'quantity': ['Quantity must not be greater than 30.']}
  • required 参数:标记该字段必须传递切被校验
  • error_messages 参数:传递字典定义错误返回信息:
def get_field_valid_msg(field_name):
return {
'required': '[%s] 字段必填' % field_name,
'type': '[%s] 字段类型不合法' % field_name, # used by Unmarshaller
'null': '[%s] 字段不能为空' % field_name,
'validator_failed': '[%s] 字段值不合法' % field_name
}
  • many 参数:同 fields.Nested 同用表示指定元素类型的数组类型,严格按照数据类型校验,fields.Nested 表示制定另一个 Schema 作为外键:
......
'components': fields.Nested(Component, required=True, many=True,
error_messages=get_field_valid_msg("组件信息")),
......
  • fields.List 类型:一类 Field 元素,可以指定元素类型,对于传递的非数组类型的元素,会自动包装为一个数组

5. 验证

  • 对于 Schema 的校验有很多方式,通过上述 Field 元素的相关参数已经实现了很多对元素的校验
  • 也可以通过定义 @validates(field_name) 装饰器定义特定属性的校验函数
  • 也可以通过定义 @validate_schema() 装饰器定义 Schema 级别的校验函数:
@validates_schema
def validate_element_type(self, value): switch = {
DpaVideoPackageElementType.TEXT : lambda x : x in DpaVideoPackageDataType.text_types(),
DpaVideoPackageElementType.IMAGE : lambda x : x in DpaVideoPackageDataType.image_types(),
DpaVideoPackageElementType.LOGO : lambda x : x in DpaVideoPackageDataType.logo_types()
} try:
if not switch[value['element_type']](value['data_type']):
raise ValidationError("组件类型和组件数据类型不匹配")
except KeyError as e:
raise ValidationError("组件类型不存在")
  • 对于一个 Schema,load() 和 loads 方法会在返回值中加入验证错误的信息:
class ImageOrImageMeta(Schema):
value = fields.String(required=True, error_messages=get_field_valid_msg("图片或图片元数据值"))
height = fields.Int(required=True, error_messages=get_field_valid_msg("图片或图片元数据高度"))
width = fields.Int(required=True, error_messages=get_field_valid_msg("图片或图片元数据宽度")) class ImageTpl(Schema):
value = fields.Dict(required=True, error_messages=get_field_valid_msg("图片模版值"))
height = fields.Int(required=True, error_messages=get_field_valid_msg("图片模版高度"))
width = fields.Int(required=True, error_messages=get_field_valid_msg("图片模版宽度")) class TextOrTextMeta(Schema):
value = fields.String(required=True, error_messages=get_field_valid_msg("文本或文本元数据值"))
default_val = fields.String(error_messages=get_field_valid_msg("文本或文本元数据默认值"))
max_length = fields.Int(required=True, error_messages=get_field_valid_msg("文本或文本元数据最大值"))
......
switch = {
DpaVideoPackageDataType.IMAGE : lambda x : ImageOrImageMeta().load(x),
DpaVideoPackageDataType.IMAGE_META : lambda x : ImageOrImageMeta().load(x),
DpaVideoPackageDataType.IMAGE_TPL : lambda x : ImageTpl().load(x),
DpaVideoPackageDataType.TEXT : lambda x : TextOrTextMeta().load(x),
DpaVideoPackageDataType.TEXT_META : lambda x : TextOrTextMeta().load(x),
} result = switch[value['data_type']](value['data'])
if result.errors:
raise ValidationError(result.errors)

4. 参考文献

Python(二)Marshmallow 库相关学习的更多相关文章

  1. Python关于PIL库的学习总结与成果展示

    一.关于PIL库的学习总结 PIL(Python Image Library)库是Python语言的第三方库,需要通过pip工具安装.安装PIL库的方法如下,需要注意,安装库的名字是pillow. : ...

  2. python 协程库gevent学习--gevent数据结构及实战(三)

    gevent学习系列第三章,前面两章分析了大量常用几个函数的源码以及实现原理.这一章重点偏向实战了,按照官方给出的gevent学习指南,我将依次分析官方给出的7个数据结构.以及给出几个相应使用他们的例 ...

  3. MySQL数据库(二)--库相关操作、表相关操作(1)、存储引擎、数据类型

    一.库相关操作 1.创建数据库 (1)语法 create database 数据库 charset utf8; (2)数据库命名规范 可以由字母.数字.下划线.@.#.$ 区分大小写 唯一性 不能使用 ...

  4. MySQL数据库(二)——库相关操作、表相关操作(一)、存储引擎、数据类型

    库相关操作.表相关操作(一).存储引擎.数据类型 一.库相关操作 1.创建数据库 (1)语法 create database 数据库 charset utf8; (2)数据库命名规范 可以由字母.数字 ...

  5. python 协程库gevent学习--gevent源码学习(二)

    在进行gevent源码学习一分析之后,我还对两个比较核心的问题抱有疑问: 1. gevent.Greenlet.join()以及他的list版本joinall()的原理和使用. 2. 关于在使用mon ...

  6. MySql学习笔记【二、库相关操作】

    命令规范 关键字.函数名称大写 数据库.表名.字段名小写 语句须以分号结尾 切换使用数据库 USE database_name 如:USE test 查看数据库列表 SHOW {DATABASES|S ...

  7. python calendar标准库基础学习

    # -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...

  8. [python]-数据科学库Numpy学习

    一.Numpy简介: Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针.这样为了保存一个简单的[1,2,3],需要有3 ...

  9. python 协程库gevent学习--gevent数据结构及实战(四)

    一不留神已经到第四部分了,这一部分继续总结数据结构和常用的gevent类,废话不多说继续. 1.Timeout错误类 晚上在调试调用第三方接口的时候,发现有些接口耗时非常多,觉得应该有个超时接口来限制 ...

随机推荐

  1. Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理

    Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理   本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...

  2. NET/Regex 处理连续空格

    问题: 就是一个字符串呀,一个字符串,里面的话有一个空格,有可能有连续空格,你遇到连续空格,把这个连续空格变成一个空格,一个空格地不处理. 代码: /// <summary> /// 处理 ...

  3. SQL Date 时间类型处理

    SQL 日期(Dates)   2019-10-17 22:17:26 当我们处理日期时,最难的任务恐怕是确保插入的日期的格式,与数据库中日期列的格式相匹配. 保存的如果是日期部分,查询不会有太大问题 ...

  4. 一款神器,批量手机号码归属地查询软件,支持导出Excel表格

    很多人查询手机号码归属地,还在一个一个百度去查太慢了,如果有几万个那么是不是要百度很久 有一款软件很多人都不知道,可以吧号码复制进去,即使里面有汉字也可以把手机号码挑出来,然后查询归属地,还具有号码去 ...

  5. PIE SDK剔除栅格块算法

    1.算法功能简介 剔除栅格块即剔除栅格小斑块功能.一幅影像图层某一区域存在碎小斑块,需要对其按照一定的条件进行剔除. PIE支持剔除栅格快算法功能的执行,下面对该算法功能进行介绍. 2.算法功能实现说 ...

  6. Python基础12

    jupyter notebook 快捷键 ”Ctrl + / ” 快速注释/撤销注释.注释整行或者整段代码.

  7. iOS7的十个更“佳”:简洁直观更受青睐

    转自:http://www.25pp.com/news/news_27792.html iOS7自发布以来一直是褒贬不一,虽然苹果还只是发布了第二个测试版,但普通用户早已经在纠结到底该不该升级iOS7 ...

  8. 2019CISCN web题赛-JustSoSo;love_math(复现)

    0x00前言 这几天从网上找个CMS源码开始练习审计,盯着众多的代码debug调呀调头晕脑胀的,还不错找到个文件读取和一个ssrf... 上月底结束的CISCN线上赛,web四道,仔细研究的2道,做出 ...

  9. linux Yum相关

    python编写,是centos 和 redhat的包管理工具,类似于 pip 常用的yum命令 Yum list 查看所有的包 Yum list python 列出所有python包 yum sea ...

  10. Django框架(十五)-- cookie和session组件

    一.cookie 1.cookie的由来 HTTP协议是无状态的.无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直 ...