JSON validation

Bocadillo has built-in support for JSON data validation within views using TypeSystem, a data validation library.

NOTE

If you're looking to validate data before saving it to a database, see Data validation (ORM). If you are looking to validate arbitrary JSON objects, read on!

How it works

JSON data validation is implemented by registering an error handler for the typesystem.ValidationError exception.

Thanks to this, you can transparently use all the features of TypeSystem and let validation fail within views: Bocadillo will format and send a 400 Bad Request error response for you.

TypeSystem comes installed with Bocadillo, and this feature is enabled by default, so you can use it right out of the box. 🎉

Example

Consider a todos application.

  1. In models.py, we define a Todo data schema.
import typesystem


class Todo(typesystem.Schema):
    title = typesystem.String(max_length=20)
    done = typesystem.Boolean(default=False)
  1. In app.py, we validate the JSON payload with the Todo schema and then create a todo item:
# todos/app.py
from bocadillo import App
from .models import Todo

app = App()


@app.route("/todos")
class TodoList:
    async def post(self, req, res):
        # NOTE: this may raise a `ValidationError` if the JSON
        # payload is invalid.
        # No need to try/except: the error handler will process
        # the exception for us!
        todo = Todo.validate(await req.json())

        # TODO: store todo item.

        res.json = dict(todo)
        res.status_code = 201

Let's try it out:

  1. Run the app using $ uvicorn todos.asgi:app.
  2. Make a request with a valid JSON payload — everything should be fine:
$ curl \
  -X POST \
  -d '{"title": "Make breakfast"}' \
  http://localhost:8000/todos
{
  "title": "Make breakfast",
  "done": false
}
  • Send an invalid payload instead (e.g. title too long) — Bocadillo should automatically return an explicit error response:
$ curl \
  -X POST \
  -d '{"title": "Buy cornflakes at the store and make breakfast"}' \
  http://localhost:8000/todos
{
  "error": "400 Bad Request",
  "status": 400,
  "detail": { "title": "Must have no more than 20 characters." }
}

This is a fairly basic example, but you can read the TypeSystem documentation to learn about more complex validation techniques.

Disabling validation error handling

If you wish to disable the ValidationError error handler, use the HANDLE_TYPESYSTEM_VALIDATION_ERROR setting:

# myproject/settings.py
HANDLE_TYPESYSTEM_VALIDATION_ERROR = False

You would then have to handle typesystem.ValidationError yourself, or implement your own error handlers in case you want to use a different data validation library.