摘要:方法對(duì)應(yīng)的是方法,它反序列化一個(gè)字典為數(shù)據(jù)結(jié)構(gòu)。某些例如和內(nèi)置了驗(yàn)證器驗(yàn)證集合時(shí),錯(cuò)誤字典將基于無(wú)效字段的索引作為鍵通過給的參數(shù)傳遞對(duì)象,可以執(zhí)行額外的驗(yàn)證驗(yàn)證函數(shù)可以返回布爾值或拋出異常。
快速上手 Declaring Schemas
首先創(chuàng)建一個(gè)基礎(chǔ)的user“模型”(只是為了演示,并不是真正的模型):
import datetime as dt class User(object): def __init__(self, name, email): self.name = name self.email = email self.created_at = dt.datetime.now() def __repr__(self): return "".format(self=self)
然后通過定義一個(gè)映射屬性名稱到Field對(duì)象的類創(chuàng)建schema:
from marshmallow import Schema, fields class UserSchema(Schema): name = fields.Str() email = fields.Email() created_at = fields.DateTime()Serializing Objects ("Dumping")
傳遞對(duì)象到創(chuàng)建的schema的dump方法,返回一個(gè)序列化字典對(duì)象(和一個(gè)錯(cuò)誤字典對(duì)象,下文講):
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"}
也可以使用dumps方法序列化對(duì)象為JSON字符串:
json_result = schema.dumps(user) pprint(json_result.data) # "{"name": "Monty", "email": "monty@python.org", "created_at": "2014-08-17T14:54:16.049594+00:00"}"Filtering output
使用only參數(shù)指定要序列化輸出的字段:
summary_schema = UserSchema(only=("name", "email")) summary_schema.dump(user).data # {"name": "Monty Python", "email": "monty@python.org"}
使用exclude參數(shù)指定不進(jìn)行序列化輸出的字段。
Deserializing Objects ("Loading")dump方法對(duì)應(yīng)的是load方法,它反序列化一個(gè)字典為python數(shù)據(jù)結(jié)構(gòu)。
load方法默認(rèn)返回一個(gè)fields字段和反序列化值對(duì)應(yīng)的字典對(duì)象:
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)}Deserializing to Objects
在Schema子類中定義一個(gè)方法并用post_load裝飾,該方法接收一個(gè)要反序列化的數(shù)據(jù)字典返回原始python對(duì)象:
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)
現(xiàn)在調(diào)用load方法將返回一個(gè)User對(duì)象:
user_data = { "name": "Ronnie", "email": "ronnie@stones.com" } schema = UserSchema() result = schema.load(user_data) result.data # =>Handling Collections of Objects
可迭代的對(duì)象集合也可以進(jìn)行序列化和反序列化。只需要設(shè)置many=True:
user1 = User(name="Mick", email="mick@stones.com") user2 = User(name="Keith", email="keith@stones.com") users = [user1, user2] schema = UserSchema(many=True) result = schema.dump(users) # OR UserSchema().dump(users, many=True) result.data # [{"name": u"Mick", # "email": u"mick@stones.com", # "created_at": "2014-08-17T14:58:57.600623+00:00"} # {"name": u"Keith", # "email": u"keith@stones.com", # "created_at": "2014-08-17T14:58:57.600623+00:00"}]Validation
Schema.load()和Schema.loads()返回值的第二個(gè)元素是一個(gè)驗(yàn)證錯(cuò)誤的字典。某些fields例如Email和URL內(nèi)置了驗(yàn)證器:
data, errors = UserSchema().load({"email": "foo"}) errors # => {"email": [""foo" is not a valid email address."]} # OR, equivalently result = UserSchema().load({"email": "foo"}) result.errors # => {"email": [""foo" is not a valid email address."]}
驗(yàn)證集合時(shí),錯(cuò)誤字典將基于無(wú)效字段的索引作為鍵:
class BandMemberSchema(Schema): name = fields.String(required=True) email = fields.Email() user_data = [ {"email": "mick@stones.com", "name": "Mick"}, {"email": "invalid", "name": "Invalid"}, # invalid email {"email": "keith@stones.com", "name": "Keith"}, {"email": "charlie@stones.com"}, # missing "name" ] result = BandMemberSchema(many=True).load(user_data) result.errors # {1: {"email": [""invalid" is not a valid email address."]}, # 3: {"name": ["Missing data for required field."]}}
通過給fields的validate參數(shù)傳遞callable對(duì)象,可以執(zhí)行額外的驗(yàn)證:
class ValidatedUserSchema(UserSchema): # NOTE: This is a contrived example. # You could use marshmallow.validate.Range instead of an anonymous function here age = fields.Number(validate=lambda n: 18 <= n <= 40) in_data = {"name": "Mick", "email": "mick@stones.com", "age": 71} result = ValidatedUserSchema().load(in_data) result.errors # => {"age": ["Validator(71.0) is False"]}
驗(yàn)證函數(shù)可以返回布爾值或拋出ValidationError異常。如果是拋出異常,其信息將保存在錯(cuò)誤字典中:
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."]}Field Validators as Methods
使用validates裝飾器注冊(cè)方法驗(yàn)證器:
from marshmallow import fields, Schema, validates, ValidationError class ItemSchema(Schema): quantity = fields.Integer() @validates("quantity") def validate_quantity(self, value): if value < 0: raise ValidationError("Quantity must be greater than 0.") if value > 30: raise ValidationError("Quantity must not be greater than 30.")strict Mode
在schema構(gòu)造器或class Meta中設(shè)置strict=True,遇到不合法數(shù)據(jù)時(shí)將拋出異常,通過ValidationError.messages屬性可以訪問驗(yàn)證錯(cuò)誤的字典:
from marshmallow import ValidationError try: UserSchema(strict=True).load({"email": "foo"}) except ValidationError as err: print(err.messages)# => {"email": [""foo" is not a valid email address."]}Required Fields
設(shè)置required=True可以定義一個(gè)必要字段,調(diào)用Schema.load()方法時(shí)如果字段值缺失將驗(yàn)證失敗并保存錯(cuò)誤信息。
給error_messages參數(shù)傳遞一個(gè)dict對(duì)象可以自定義必要字段的錯(cuò)誤信息:
class UserSchema(Schema): name = fields.String(required=True) age = fields.Integer( required=True, error_messages={"required": "Age is required."} ) city = fields.String( required=True, error_messages={"required": {"message": "City required", "code": 400}} ) email = fields.Email() data, errors = UserSchema().load({"email": "foo@bar.com"}) errors # {"name": ["Missing data for required field."], # "age": ["Age is required."], # "city": {"message": "City required", "code": 400}}Partial Loading
通過指定partial參數(shù),可以忽略某些缺失字段的required檢查:
class UserSchema(Schema): name = fields.String(required=True) age = fields.Integer(required=True) data, errors = UserSchema().load({"age": 42}, partial=("name",)) # OR UserSchema(partial=("name",)).load({"age": 42}) data, errors # => ({"age": 42}, {})
或者設(shè)置partial=True忽略所有缺失字段的required檢查:
class UserSchema(Schema): name = fields.String(required=True) age = fields.Integer(required=True) data, errors = UserSchema().load({"age": 42}, partial=True) # OR UserSchema(partial=True).load({"age": 42}) data, errors # => ({"age": 42}, {})Schema.validate
使用Schema.validate()可以只驗(yàn)證輸入數(shù)據(jù)而不反序列化:
errors = UserSchema().validate({"name": "Ronnie", "email": "invalid-email"}) errors # {"email": [""invalid-email" is not a valid email address."]}Specifying Attribute Names
默認(rèn)情況下schema序列化處理和field名稱相同的對(duì)象屬性。對(duì)于屬性和field不相同的場(chǎng)景,通過attribute參數(shù)指定field處理哪個(gè)屬性:
class UserSchema(Schema): name = fields.String() email_addr = fields.String(attribute="email") date_created = fields.DateTime(attribute="created_at") user = User("Keith", email="keith@stones.com") ser = UserSchema() result, errors = ser.dump(user) pprint(result) # {"name": "Keith", # "email_addr": "keith@stones.com", # "date_created": "2014-08-17T14:58:57.600623+00:00"}Specifying Deserialization Keys
默認(rèn)情況下schema反序列化處理鍵和field名稱相同的字典。可以通過load_from參數(shù)指定額外處理的字典鍵值:
class UserSchema(Schema): name = fields.String() email = fields.Email(load_from="emailAddress") data = { "name": "Mike", "emailAddress": "foo@bar.com" } s = UserSchema() result, errors = s.load(data) #{"name": u"Mike", # "email": "foo@bar.com"}Specifying Serialization Keys
如果要序列化輸出不想使用field名稱作為鍵,可以通過dump_to參數(shù)指定(和load_from相反):
class UserSchema(Schema): name = fields.String(dump_to="TheName") email = fields.Email(load_from="CamelCasedEmail", dump_to="CamelCasedEmail") data = { "name": "Mike", "email": "foo@bar.com" } s = UserSchema() result, errors = s.dump(data) #{"TheName": u"Mike", # "CamelCasedEmail": "foo@bar.com"}Refactoring: Implicit Field Creation
當(dāng)schema中有很多屬性時(shí),為每個(gè)屬性指定field類型會(huì)產(chǎn)生大量的重復(fù)工作,尤其是大部分屬性為原生的python數(shù)據(jù)類型時(shí)。
class Meta允許開發(fā)人員指定序列化哪些屬性,Marshmallow會(huì)基于屬性類型選擇合適的field類型:
# 重構(gòu)UserSchema class UserSchema(Schema): uppername = fields.Function(lambda obj: obj.name.upper()) class Meta: fields = ("name", "email", "created_at", "uppername") user = User(name="erika", email="marshmallow@126.com") schema = UserSchema() result = schema.dump(user) print(result.data) # {"created_at": "2019-05-20T15:45:27.760000+00:00", "uppername": "ERIKA", "name": "erika", "email": "marshmallow@126.com"}
除了顯式聲明的field外,使用additional選項(xiàng)可以指定還要包含哪些fields。以下代碼等同于上面的代碼:
class UserSchema(Schema): uppername = fields.Function(lambda obj: obj.name.upper()) class Meta: # No need to include "uppername" additional = ("name", "email", "created_at")Ordering Output
設(shè)置ordered=True可以維護(hù)序列化輸出的field順序,此時(shí)序列化字典為collections.OrderedDict類型:
from collections import OrderedDict class UserSchema(Schema): uppername = fields.Function(lambda obj: obj.name.upper()) class Meta: fields = ("name", "email", "created_at", "uppername") ordered = True u = User("Charlie", "charlie@stones.com") schema = UserSchema() result = schema.dump(u) assert isinstance(result.data, OrderedDict) # marshmallow"s pprint function maintains order pprint(result.data, indent=2) # { # "name": "Charlie", # "email": "charlie@stones.com", # "created_at": "2014-10-30T08:27:48.515735+00:00", # "uppername": "CHARLIE" # }"Read-only" and "Write-only" Fields
在web API上下文中,dump_only和load_only參數(shù)分別類似于只讀和只寫的概念:
class UserSchema(Schema): name = fields.Str() # password is "write-only" password = fields.Str(load_only=True) # created_at is "read-only" created_at = fields.DateTime(dump_only=True)更多教程
marshmallow之schema嵌套
marshmallow之自定義Field
marshmallow之Schema延伸功能
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/43841.html
摘要:有三種方式創(chuàng)建自定義的。下面的例子判斷某個(gè)對(duì)象是否是某個(gè)對(duì)象的作者,以及的屬性是否出現(xiàn)單詞自定義錯(cuò)誤信息字段驗(yàn)證產(chǎn)生的錯(cuò)誤信息可以在類級(jí)別或?qū)嵗?jí)別配置。在類級(jí)別時(shí),可以定義為錯(cuò)誤碼和錯(cuò)誤信息的字典映射在類實(shí)例化時(shí),給參數(shù)傳參對(duì)象 有三種方式創(chuàng)建自定義的field。 創(chuàng)建Field類的子類 創(chuàng)建繼承自marshmallow.fields.Field類的子類并實(shí)現(xiàn)_serialize和/...
摘要:創(chuàng)建實(shí)例時(shí)如果傳遞了,表示需要接收輸入數(shù)據(jù)集合,裝飾器注冊(cè)預(yù)處理和后處理方法時(shí)需要傳遞參數(shù)。 預(yù)處理和后處理方法 數(shù)據(jù)的預(yù)處理和后處理方法通過pre_load, post_load, pre_dump和post_dump裝飾器注冊(cè): from marshmallow import Schema, fields, pre_load class UserSchema(Schema): ...
摘要:嵌套可以嵌套使用以表示對(duì)象間的關(guān)系如外鍵關(guān)系。在下面的例子中,和對(duì)象是一對(duì)多的關(guān)系必須使用或參數(shù)避免無(wú)限遞歸也可以使用導(dǎo)入模塊的方式傳遞嵌套,如自嵌套給傳遞字符串參數(shù)表示和對(duì)象本身的關(guān)系 schema嵌套 schema可以嵌套使用以表示對(duì)象間的關(guān)系(如外鍵關(guān)系)。 例如下例中Blog有一個(gè)用User對(duì)象表示的author屬性: import datetime as dt class ...
摘要:閱讀本期周刊,你將快速入門,開啟甜蜜之旅。然則的原理負(fù)責(zé)發(fā)送以及處理消息,創(chuàng)建消息隊(duì)列并不斷從隊(duì)列中取出消息交給,則用于保存消息。 showImg(/img/bVCN99?w=900&h=385); 2016 年 8 月,Android 7.0 Nougat(牛軋?zhí)牵┱桨l(fā)布,那么問題來(lái)了,你 Marshmallow 了么(? -? ?) Cupcake、Donut、Gingerbre...
閱讀 2851·2021-09-22 15:43
閱讀 4686·2021-09-06 15:02
閱讀 845·2019-08-29 13:55
閱讀 1679·2019-08-29 12:58
閱讀 3061·2019-08-29 12:38
閱讀 1206·2019-08-26 12:20
閱讀 2264·2019-08-26 12:12
閱讀 3311·2019-08-23 18:35