如何将 Schema.from_dict() 用于嵌套字典?

ort*_*tiv 3 marshmallow

我正在尝试使用具有一些列表作为元素的嵌套字典创建一个 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"
                        }
             }]
         }
    }  
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

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)
Run Code Online (Sandbox Code Playgroud)

实际结果:

"{\"field1\": 5, \"field2\": false}"
Run Code Online (Sandbox Code Playgroud)

Nic*_*nov 5

选项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}]}}
Run Code Online (Sandbox Code Playgroud)

选项 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}
Run Code Online (Sandbox Code Playgroud)

感觉它很适合你的情况。

注释

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

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