• marshmallow库的简单学习

    • 一、简单说明
    • 二、创建Schema类
    • 三、序列化和反序列化
      • 1、定义
      • 2、序列化
      • 3、反序列化
      • 4、部分序列化
      • 5、部分反序列化(这部分应放在特殊用法)
    • 四、数据校检
    • 五、特殊用法

marshmallow库的简单学习

marshmallow是一个简单序列化/反序列化模块。
它可以很轻松的做到
- object-->dict
- objects-->list

等序列化操作,同时经过添加简单的函数做到
- dict-->object
- list-->objects

等反序列化操作。
同时,它对于数据的校检非常友好,有多种校检方式,同时相对于Schema库,它可以更有针对性的校检数据,序列化数据等(例如只取某些数据,只校检某些数据等)。

一、简单说明

marshmallow库非常易于使用,下面将以实际的代码演示如何使用这个库。
先明确下使用流程。
创建类–>创建Schema类–>(创建ValidSchema类)
序列化<—>反序列化

二、创建Schema类

创建基础的类

# -*- coding:utf-8 -*-from datetime import date
from marshmallow import Schema, fields, pprint, post_load
from marshmallow import ValidationError, validate, validatesclass Artist(object):"""基础艺术家类"""def __init__(self, name):self.name = nameclass Album(object):"""基础专辑类"""def __init__(self, title, release_date, artist):self.title = titleself.release_date = release_dateself.artist = artist

根据自己的类创建对应的Schema类,继承自marshmallow的Schema类。

class ArtistSchema(Schema):"""艺术家的schema类"""name = fields.Str()class AlbumSchema(Schema):"""专辑的schema类"""title = fields.Str()release_date = fields.Date()artist = fields.Nested(ArtistSchema())

可以观察到,Schema类的字段和基础类的成员命名一致,在这里先保持一致,后面会对字段进一步说明;同时可以观察到Schema里对数据类型进行了限定,例如title只能是字符串,release_date只能是日期格式,这算是数据校检的第一步类型校检。

三、序列化和反序列化

1、定义

我之前一直不能理解什么是序列化,什么是反序列化,它到底有什么用。
维基定义是【序列化(serialization)在计算机科学的资料处理中,是指将数据结构或物件状态转换成可取用格式(例如存成档案,存于缓冲,或经由网络中传送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始物件相同语义的副本。】
通俗的说法就是将一个数据处理成可以存储或者传输的形式,这个过程叫序列化,反过来,将某种形式的数据处理成可以使用的数据就是反序列化。
举个python上的例子。python有个内建dict类型,也就是字典类型,可以方便的处理键值对数据,这个数据暂存于内存中,如何将它保存或者将它传输,最简单的方法就是json.dump(),将数据保存在json文件里,这个过程就称之为序列化。反过来,你拿到了一个json文件,通过json.load(),将json文件里的数据转成了dict就可以直接使用,这个过程就称之为反序列化。

2、序列化

marshmallow可以对一个object进行序列化成一个dict,同时可以对一群object进行序列化成一个list。
单个object的序列化:
下面是序列化的操作,可以看到进行了两次序列化,一次输出成dict类型,一次输出成str类型。

# 单个object,即object-->dict
bowie = Artist(name='David Bowie')
album = Album(artist=bowie, title='Hunky Dory', release_date=date(1971, 12, 17))schema = AlbumSchema()
# 单个object的序列化
# schema.dump(obj) == obj-->dict
# schema.dumps(obj) == obj-->str
result_dict = schema.dump(album)
result_str = schema.dumps(album)pprint(result_dict, indent=2)
pprint(type(result_dict))
pprint(result_str, indent=2)
pprint(type(result_str))

这是输出的结果。

{ u'artist': { u'name': u'David Bowie'},u'release_date': '1971-12-17',u'title': u'Hunky Dory'}
<type 'dict'>
'{"release_date": "1971-12-17", "title": "Hunky Dory", "artist": {"name": "David Bowie"}}'
<type 'str'>

序列化之后我们就可以进行保存或者传输,dict存储为json,str存储为文本。

多个object的序列化:
下面是序列化的操作,可以看到进行了两次序列化,一次输出成list类型,其中list的每一个元素都是dict类型,一次输出成str类型。多个object序列化不需要变动Schema类,只要添加many=True这个属性就可以了。

# 多个object,即objects-->list
alice = Artist(name='Alice')
bob = Artist(name='Bob')
cinderella = Artist(name='Cinderella')
alice_album = Album(title='To Alice', release_date=date(1971, 01, 01), artist=alice)
bob_album = Album(title='Kill Bob', release_date=date(1972, 02, 02), artist=bob)
cinderella_album = Album(title='Cinderella', release_date=date(1973, 03, 03), artist=cinderella)
album = [alice_album, bob_album, cinderella_album]## Schema类字段many=True
schema = AlbumSchema(many=True)
# 多个object的序列化
# schema.dump(obj_list) == obj_list-->dict_list
# schema.dumps(obj_list) == obj_list-->str
result_list = schema.dump(album)
result_str = schema.dumps(album)
pprint(result_list, indent=2)
pprint(result_str, indent=2)

这是输出的结果。

[ { u'artist': { u'name': u'Alice'},u'release_date': '1971-01-01',u'title': u'To Alice'},{ u'artist': { u'name': u'Bob'},u'release_date': '1972-02-02',u'title': u'Kill Bob'},{ u'artist': { u'name': u'Cinderella'},u'release_date': '1973-03-03',u'title': u'Cinderella'}]
'[{"release_date": "1971-01-01", "title": "To Alice", "artist": {"name": "Alice"}}, {"release_date": "1972-02-02", "title": "Kill Bob", "artist": {"name": "Bob"}}, {"release_date": "1973-03-03", "title": "Cinderella", "artist": {"name": "Cinderella"}}]'

序列化之后我们就可以进行保存或者传输,list不能直接存储,但是可以作为dict的一个value存储为json,str存储为文本。

3、反序列化

marshmallow可以对一个dict或str进行反序列化成一个object,同时可以对一个list或str进行反序列化成一个list,此时list的每个元素是object
注意:marshmallow默认并不能反序列化成object,但添加一个简单的方法就可以实现。

class AlbumSchema(Schema):"""专辑的schema类"""title = fields.Str()release_date = fields.Date()artist = fields.Nested(ArtistSchema())@post_load()def make_album(self, data):"""添加了post_load()装饰器的方法,在反序列化时会执行这个逻辑"""return Album(**data)

单个object的反序列化:
下面是反序列化的操作,可以看到进行了两次反序列化,一次将dict类型输出成object,一次将str类型输出object

# 单个object的反序列化
# schema.load(dict) == dict-->dict
# schema.loads(str) == str-->dict
# if you want dict-->object, you should add a method in 'class AlbumSchema', then use the 'post_load()' decorator
# result_dict  result_str是序列化后的结果
origin_dict = schema.load(result_dict)
origin_str = schema.loads(result_str)
pprint(origin_dict)
pprint(type(origin_dict))
pprint(origin_str)
pprint(type(origin_str))

这是输出的结果。

<__main__.Album object at 0x7f4784e48c10>
<class '__main__.Album'>
<__main__.Album object at 0x7f4784e48b90>
<class '__main__.Album'>

可以看出已经变成了对象。

多个object的反序列化:

# 多个object的反序列化
# schema.load(list) == list-->list
# schema.loads(str) == str-->list
# 在这里,反序列化后会生成三个对象的列表,即列表的每一个元素都是一个实例
origin_list = schema.load(result_list)
origin_str = schema.loads(result_str)
pprint(origin_list)
pprint(type(origin_list))
pprint(origin_str)
pprint(type(origin_str))

以下是结果,可以很清楚的看到反序列化为了一个list,list的每个元素是object

[<__main__.Album object at 0x7f51eb7ebed0>,<__main__.Album object at 0x7f51eb7ebf10>,<__main__.Album object at 0x7f51eb7ebf50>]
<type 'list'>
[<__main__.Album object at 0x7f51eb7ebf90>,<__main__.Album object at 0x7f51eb7ebfd0>,<__main__.Album object at 0x7f51eb781050>]
<type 'list'>

4、部分序列化

之前的序列化都是对object完整的序列化操作,假设现在只需要传输或者保存object的某些字段该怎么做?Schema类提供了一个only属性,只序列化only内的字段。

# 不加only
schema = AlbumSchema()
result = schema.dump(alice_album)
pprint(result)
# 添加only=['title', 'release_date']
schema = AlbumSchema(only=['title', 'release_date'])
result = schema.dump(alice_album)
pprint(result)
# 不加only输出结果
{u'release_date': '1971-01-01', u'title': u'To Alice', u'artist': {u'name': u'Alice'}}
# 添加only输出结果
{u'release_date': '1971-01-01', u'title': u'To Alice'}

我们需要哪些字段就将哪些字段加到only列表中,这样可以减少序列化后的数据量,传输也更轻松。

5、部分反序列化(这部分应放在特殊用法)

[官方文档(https://marshmallow.readthedocs.io/en/3.0/quickstart.html) 这部分的标题是Partial Loading,意为部分加载,它指的是可以不对Schema类里的所有字段进行校检。

举个简单的例子,定义了一个有十个字段的类,又定义了一个相关的Schema类。假设我需要对传来的部分数据做校检该怎么做?直接放进schema.load()必定会出错,这时候就需要用到partial属性。
(但还是会有个前提,即Schema类中不实现生成对象的方法)。

四、数据校检

终于来到了数据校检部分。数据校检可以简单地分为数据类型检查和数据值的检查。marshmallow的数据校检过程中甚至可以主动格式化传来的数据,例如使其大写或者小写等。

  • fields类型校检
  • fields的required属性校检
  • fields的validate属性校检
  • fields的method校检

可以看出,主要是围绕fields进行校检,在看校检过程之前先解释下ValidationError和Field概念。

ValidationError:marshmallow里的错误类型,通过try——except捕捉到这个错误后,可以直接输出message信息,它将以字典形式放回所有校检失败的原因
Field:各种类型数据的字段类

下面将直接通过代码说明校检过程。

class User(object):"""用户类"""def __init__(self, name, age, email):self.name = nameself.age = ageself.email = emailclass UserSchema(Schema):"""user普通schema类"""name = fields.Str()age = fields.Number()email = fields.Email()class ValidUserSchema(UserSchema):"""user有效值判断schema有多种判断方式"""# 先是判断name是不是Str类型# fields添加了required=True属性,指的是name必须存在name = fields.Str(required=True)# 先是判断email是不是Email类型# field添加了validate属性,validate可以用多种方式校检,这里用到的是正则匹配# email必须正则匹配特定的规则email = fields.Email(validate=validate.Regexp('[0-9a-zA-Z.]+@woqutech.com'))# age可以通过设定validate进行值的范围判断age = fields.Number(validate=lambda n: 18 <= n <= 41)age = fields.Number(validate=validate.Range(18, 41))# 下面是fields的method校检方式age = fields.Number()@validates('age')def validate_age(self, value):"""age同样可以通过method进行值的判断,需要装饰器validates(key_name)"""if value < 0:raise ValidationError('Age should not < 0')if value > 100:raise ValidationError('Age should not > 100')user = {'name': 'Alice', 'age': -12, 'email': '123.4?5@woqutech.com'}try:result = ValidUserSchema().load(user)
except ValidationError as e:print(e.message)

五、特殊用法

  • Partial Loading
  • Handling Unknown Fields
  • Schema.validate
  • Specifying Attribute Names
  • Specifying Serialization/Deserialization Keys
  • Refactoring: Implicit Field Creation
  • Ordering Output
  • “Read-only” and “Write-only” Fields
  • Specify Default Serialization/Deserialization Values

参考文档:
快速开始
marshmallow官方文档

marshmallow库的简单学习相关推荐

  1. nanomsg-pynng库的简单学习笔记

    ''' ''' ''' About pynng (python nanomsg next generation 可用的协议有以下几个: Pair0 Pair1 Req0 / Rep0 Pub0 / S ...

  2. [EntLib]微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇...

    在完成了后,今天开始介绍企业库中的新模块:Cryptographer(加密模块),这个模块在日常的大多数项目的作用非常重要,例如:网站会员密码.身份证号.网站配置等,通过对信息进行加密可以保证项目数据 ...

  3. Python学习-Matplotlib库绘制简单点阵图、线型图操作

    Python学习-Matplotlib库绘制简单散点图图和线型图.标签设置以及刻度线设置操作 目录 1.Matplotlib绘图细节的简单理解 2.绘制点图.线型图 3.给图表设置复杂标注 4.移动刻 ...

  4. [EntLib]微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇...

    本文是为后面的学习之路做铺垫,简单介绍下企业库中的Validation模块的一些相关知识,包括Validation模块的简介.用途.使用方法.默认提供的多种验证器的介绍等. 一.简介及用途 在实际的项 ...

  5. [Python学习]PycURL简单学习 - limodou的学习记录 - limodou是一个程序员,他关心的焦点是Python, DocBook, Open Source …...

    [Python学习]PycURL简单学习 - limodou的学习记录 - limodou是一个程序员,他关心的焦点是Python, DocBook, Open Source - [Python学习] ...

  6. (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)...

    原文地址:http://www.cnblogs.com/kyo-yo/archive/2010/11/01/Learning-EntLib-Tenth-Decoupling-Your-System-U ...

  7. python如何安装panda数据库_在Pycharm中安装Pandas库方法(简单易懂)

    开发环境的搭建是一件入门比较头疼的事情,在上期的文稿基础上,增加一项Anaconda的安装介绍.Anaconda是Python的一个发行版本,安装好了Anaconda就相当于安装好了Python,并且 ...

  8. 2020 年,开启现代库的基建学习 —— 从项目演进看前端工程化发展

    这篇文章想重点来和大家聊一下「现代库编写」的话题,相信技术和思维上,对你会有启发. 库,不仅是能用 国庆长假已过,2019 年进入最后一个季度,前端技术和解决方案每时每刻在确立着新的格局.「如何写好一 ...

  9. python123九宫格输入_使用python PIL库实现简单验证码的去噪方法步骤

    字符型图片验证码识别完整过程及Python实现的博主,我的大部分知识点都是从他那里学来的. 想要识别验证码,收集足够多的样本后,首先要做的就是对验证码原始图片进行处理,对验证码识别分类之前,一般包括: ...

最新文章

  1. BeanUtils工具类,简化数据封装
  2. excel 树结构json_写一个上传excel表格,解析成 json 的接口
  3. SIFT算法总结:用于图像搜索
  4. 牛客挑战赛30 C 小G砍树 换根dp+组合
  5. RTX5 | 事件标志组01 - 创建事件标志组
  6. Hibernate-面试题
  7. 【Java】JDK8新特性之函数式接口
  8. c语言输出数字菱形北京理工大学,C语言程序的设计—北京理工大学MOOC提交作业.docx...
  9. 第二章 吸取jQuery之选择器和包装集
  10. 第一次使用博客及Coursera课程体验
  11. LFSR(线性反馈移位寄存器)
  12. 根据省份id查询当前的省会/简称/省会城市
  13. 计算机使用的显示器有哪些重要参数,正确选择适合自己的显示器,电脑显示器参数详解,看完秒懂!...
  14. Win10 Ubuntu 制作多系统U盘
  15. D - 魔咒词典 HDU—1880(双Hash值和map||Hash+二分)
  16. 2022年黑客书籍推荐
  17. vue结合饿了么_vue-饿了么项目总结
  18. vue之Excel导出和导入
  19. 《约会专家》拖车【约会宝典】总结
  20. xp系统可用的远程投屏软件_Windows XP电脑投屏

热门文章

  1. (五)图片压缩 —— 优化图片文件、内存
  2. stm32C8t6 通用定时器输出PWM+定时中断控制板载LED
  3. Windows系统的命令窗口
  4. 经方败案群20150303李小荣讲桂枝芍药知母汤
  5. Learning to Rank(以下简称L2R)
  6. Learning to Rank 简介(转载)
  7. JavaWeb - 小米商城:商品添加到购物车
  8. 敲击键盘后字符怎么出现在显示器
  9. vim autoformat php,vim - 如何在VI中整理HTML文件的缩进?
  10. 小程序真机调试连接本地服务器进行调试