首页 > 解决方案 > 如何将 Schema.from_dict() 用于嵌套字典?

问题描述

我正在尝试使用具有一些列表作为元素的嵌套字典创建一个 Schema 类。但是,当我执行 dumps() 时,只会转储顶级元素。

有一个返回某些事物列表的rest api,例如。用户列表。但架构是这样的,某些聚合细节在顶层发送,数据看起来像这样。这是我期望的输出:

   {
        "field1": 5,
        "field2": false,
        "field3": {
            "field4": 40,
            "field5": [
                        {
                            "field6": "goo goo gah gah",
                            "field7": 99.341879,
                            "field8": {
                                "field9": "goo goo gah gah",
                                "field10": "goo goo gah gah"
                        }
             }]
         }
    }  

这是我的代码:

MySchema = Schema.from_dict(
   {
        "field1": fields.Int(),
        "field2": fields.Bool(),
        "field3": {
            "field4": fields.Int(),
            "field5": [
                        {
                            "field6": fields.Str(),
                            "field7": fields.Float(),
                            "field8": {
                                "field9": fields.Str(),
                                "field10": fields.Str()
                        }
             }]
         }
    }            
)

#Then use it like:

response = MySchema().dumps(data)

实际结果:

"{\"field1\": 5, \"field2\": false}"

标签: marshmallow

解决方案


选项1

您正在寻找几个嵌套模式,它们通过以下方式相互连接fields.Nested

from marshmallow import Schema, fields


Field8Schema = Schema.from_dict({
    "field9": fields.Str(), 
    "field10": fields.Str()
})

Field5Schema = Schema.from_dict({
    "field6": fields.Str(),
    "field7": fields.Float(),
    "field8": fields.Nested(Field8Schema),
})

Field3Schema = Schema.from_dict({
    "field4": fields.Int(), 
    "field5": fields.List(fields.Nested(Field5Schema))
})

MySchema = Schema.from_dict({
    "field1": fields.Int(),
    "field2": fields.Bool(),
    "field3": fields.Nested(Field3Schema),
})

MySchema().dump(data)

# {'field2': False,
#  'field1': 5,
#  'field3': {'field4': 40,
#   'field5': [{'field6': 'goo goo gah gah',
#     'field8': {'field9': 'goo goo gah gah', 'field10': 'goo goo gah gah'},
#     'field7': 99.341879}]}}

选项 2

如果嵌套不会那么深,则使用起来可能更简单,即文档decorators中建议的嵌套和取消嵌套数据:

class UserSchema(Schema):
    @pre_load(pass_many=True)
    def remove_envelope(self, data, many, **kwargs):
        namespace = 'results' if many else 'result'
        return data[namespace]

    @post_dump(pass_many=True)
    def add_envelope(self, data, many, **kwargs):
        namespace = 'results' if many else 'result'
        return {namespace: data}

感觉它很适合你的情况。

注释

我建议不要使用from_dict这种复杂数据,因为它的可读性较差,而是切换到基于类的模式。

文档中有很多很好的嵌套示例


推荐阅读