Skip to main content

Validate top-level lists with all the power of marshmallow

Project description

marshmallow-toplevel

Load and validate top-level lists with all the power of marshmallow.

Installation

pip install marshmallow-toplevel

Usage

from marshmallow import fields
from marshmallow_toplevel import TopLevelSchema


class BatchOfSomething(TopLevelSchema):
    _toplevel = fields.Nested(
        SomethingSchema,
        required=True,
        many=True,
        validate=any_validation_logic_applied_to_list
    )

Rationale

Imagine that you have an API endpoint (or any other program that accepts user input), which is intended to accept multiple blog articles and save them to a database. Semantically, your data is a list of dictionaries:

[
    {"id": 1, "title": "Hello World!"},
    {"id": 2, "title": "Yet another awesome article."},
    ...
]

You describe article object schema and put constraints on your data:

from marshmallow import Schema, fields, validate


class ArticleSchema(Schema):
    id = fields.Int(required=True)
    title = fields.Str(required=True, validate=validate.Length(min=2, max=256))

But you also want to put some constraints onto outer list itself, for example, you want it to have length between 1 and 10. How do you describe it in terms of marshmallow?

Obvious solution: nest your data

class BatchOfArticles(Schema):
    articles = fields.Nested(
        ArticleSchema,
        required=True,
        many=True,
        validate=validate.Length(1, 10)
    )

But now a client have to send data this way, with this extra dictionary around:

{
    "articles": [
        {"id": 1, "title": "Hello World!"},
        {"id": 2, "title": "Yet another awesome article."},
        ...
    ]
}

It makes your API not so beautiful and user-friendly.

Good solution: use marshmallow-toplevel

With marshmallow-toplevel you can describe you data this way:

from marshmallow_toplevel import TopLevelSchema


class BatchOfArticles(TopLevelSchema):
    _toplevel = fields.Nested(
        ArticleSchema,
        required=True,
        many=True,
        validate=validate.Length(1, 10)
    )

Notice that schema inherits from TopLevelSchema and uses this special _toplevel key. It means that the field under this key describes top level object. You can define any constrains that you can define in marshmallow and it will just work:

schema = BatchOfArticles()

# validation should fail
errors = schema.validate([])
assert errors  # length < 1
errors = schema.validate([{"id": i, "title": "title"} for i in range(100)])
assert errors  # length > 10

# validation should succeed
errors = schema.validate([{"id": i, "title": "title"} for i in range(5)])
assert not errors

You can also use load for this schema as usual:

data = schema.load([{"id": "10", "title": "wow!"}])
print(data)
# [{"id": 10, "title": "wow!"}]

Now a client can send data as a list without redundancy.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for marshmallow-toplevel, version 0.1.2
Filename, size File type Python version Upload date Hashes
Filename, size marshmallow_toplevel-0.1.2-py3-none-any.whl (3.8 kB) File type Wheel Python version py3 Upload date Hashes View hashes
Filename, size marshmallow-toplevel-0.1.2.tar.gz (4.1 kB) File type Source Python version None Upload date Hashes View hashes

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page