我已经定义了一个需要数据的POST调用:
{
"one" : "hello",
"two" : "world",
"three" : {
"ab": "123",
"cd": false
}
}
为此,我能够定义one
和two
,但不确定定义three
的权利是什么。如何在棉花糖中指定 JSON 字段?我能够定义基本字段,例如:
from marshmallow import Schema, post_load, fields
class Foo(object):
def __init__(self, one, two=None):
self.one = one
self.two = two
class MySchema(Schema):
one = fields.String(required=True)
two = fields.String()
@post_load
def create_foo(self, data, **kwargs):
return Foo(**data)
如何在MySchema
中定义three
?我应该:
- 只需将其作为字符串并进行操作以使用
json.loads()/json.dumps()
将其加载为 JSON ?或者有没有办法正确定义它? - 将其定义为
fields.Dict
? - 我可以为此字段定义单独的
Schema
吗 - 我应该延长
field.Field
吗?
我正在看 https://marshmallow.readthedocs.io/en/3.0/api_reference.html,虽然仍然不确定。JSON 子字段或嵌套 JSON 似乎是一个常见的用例,但我找不到与此相关的任何内容。
这可以通过嵌套架构来完成: https://marshmallow.readthedocs.io/en/3.0/nesting.html
您的架构将如下所示:
class MySchema(Schema):
one = fields.String(required=True)
two = fields.String()
three = fields.Nested(ThreeSchema)
class ThreeSchema(Schema):
ab = fields.String()
cd = fields.Boolean()
您可以创建自己的字段
import json
from marshmallow import fields
class JSON(fields.Field):
def _deserialize(self, value, attr, data, **kwargs):
if value:
try:
return json.loads(value)
except ValueError:
return None
return None
...
from marshmallow import fields, Schema
from schemas.base import JSON
class ObjectSchema(Schema):
id = fields.Integer()
data = JSON()
在字段中支持任意嵌套值,而不是为它们定义架构,则可以使用:
-
fields.Dict()
(接受任意 Pythondict
,或者等效地接受任意 JSON 对象(,或 -
fields.Raw()
(对于任意 Python 对象,或者等效地,任意 JSON 值(
您可以运行的示例脚本,该脚本基于问题中的示例使用上述两个脚本:
import json
from marshmallow import Schema, fields, post_load
class Foo(object):
def __init__(self, one, two=None, three=None, four=None):
self.one = one
self.two = two
self.three = three
self.four = four
class MySchema(Schema):
one = fields.String(required=True)
two = fields.String()
three = fields.Dict()
four = fields.Raw()
@post_load
def create_foo(self, data, **kwargs):
return Foo(**data)
post_data = json.loads(
"""{
"one" : "hello",
"two" : "world",
"three" : {
"ab": "123",
"cd": false
},
"four" : 567
}"""
)
foo = MySchema().load(post_data)
print(foo.one)
print(foo.two)
print(foo.three)
print(foo.four)