Flask Marshmallow JSON 个字段

Flask Marshmallow JSON fields

我已经定义了一个需要数据的 POST 调用:

{
    "one" : "hello",
    "two" : "world",
    "three" : { 
                "ab": "123", 
                "cd": false 
              }
}

为此,我可以定义onetwo,但不确定定义three的正确性。如何在 Marshmallow 中指定 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?我应该:

  1. 简单地将它作为一个字符串并进行操作以使用json.loads()/json.dumps()将其加载为json?或者有没有办法正确定义它?
  2. 定义为 fields.Dict?
  3. 我可以为这个字段定义一个单独的Schema
  4. 我应该延长 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()(接受任意 Python dict,或者等效地,任意 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)