'how to python marshmallow nested directory in a list

i am learning how to validate using marshamallow and i want to validate a field that is a list of dictonaries such my_list = [ {"my_fild":1}, {"my_field":2} ] reading the documentation from https://marshmallow.readthedocs.io/en/stable/nesting.html say i can put a field.List with a Nested field, but when i try it i get

{'a_list': {0: {'my_key': ['Not a valid mapping type.']}, 1: {'my_key': ['Not a valid mapping type.']}}}

wonder why is that.

from marshmallow import Schema, fields, ValidationError
from pprint import pprint


class UserSchema(Schema):
    name = fields.String(required=True)
    email = fields.Email(required=True)


class SomeDict(Schema):
    # field my_key should be
    my_key = fields.Dict(keys=fields.Str(), values=fields.Int())


class BlogSchema(Schema):
    title = fields.String(required=True)
    author = fields.Nested(UserSchema, required=True)
    some_dicts = fields.Dict(required=True, keys=fields.Str(), values=fields.Str())
    # i am nesting SomeDict
    a_list = fields.List(fields.Nested(SomeDict), required=True)


j = {
    "title": "bla",
    "author": {"name": "ble", "email": "[email protected]"},
    "some_dicts": {"one": "one", "two": "2"},
    # i want to pass a list of dictionaries
    "a_list": [ {"my_key": 1}, {"my_key": 2} ]
}

result = BlogSchema()

try:
    result = BlogSchema().load(j)
except ValidationError as err:
    print(err.messages)

shouldn't the 'SomeDict' class should work? thanks guys for the help =)



Solution 1:[1]

thanks Jacques, just leaving the full answer showing the 2 approachs.

from marshmallow import Schema, fields, ValidationError


class UserSchema(Schema):
    name = fields.String(required=True)
    email = fields.Email(required=True)


class SomeDict(Schema):
    key1 = fields.Str(required=True)
    key2 = fields.Str(required=True)


class BlogSchema(Schema):
    title = fields.String(required=True)
    author = fields.Nested(UserSchema, required=True)
    some_dicts = fields.Dict(required=True, keys=fields.Str(), values=fields.Str())
    a_list = fields.List(fields.Dict(keys=fields.Str(), values=fields.Int()), required=True)
    b_list = fields.List(fields.Nested(SomeDict))

j = {
    "title": "bla",
    "author": {"name": "ble", "email": "[email protected]"},
    "some_dicts": {"one": "one", "two": "2"},
    "a_list": [ {"my_key1": 1}, {"my_key2": 2} ],
    "b_list": [{"key1": "st1", "key2": "b1"}, {"key1": "st2", "key2": "b2"} ]
}

result = BlogSchema()

try:
    result = BlogSchema().load(j)
except ValidationError as err:
    print(err.messages)

Solution 2:[2]

The issue comes from the fact that SomeDict is a class with a dict attribute named my_key, whereas your data is just a dict.

Collections of objects can help here but if you use a nested schema, your data needs to change a bit to include the name of the dict field.

class BlogSchema(Schema):
    title = fields.String(required=True)
    author = fields.Nested(UserSchema, required=True)
    some_dicts = fields.Dict(required=True, keys=fields.Str(), values=fields.Str())
    # i am nesting SomeDict
    a_list = fields.Nested(SomeDict(many=True))

j = {
    "title": "bla",
    "author": {"name": "ble", "email": "[email protected]"},
    "some_dicts": {"one": "one", "two": "2"},
    # i want to pass a list of dictionaries
    "a_list": [ {'my_key': {"my_key": 1}}, {'my_key': {"my_key": 2}} ]
}

Or if you keep your data the same:

a_list = fields.List(fields.Dict(keys=fields.Str(), values=fields.Int()), required=True)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 pelos
Solution 2