Flask-jsonapi

JSONAPI 1.0 server implementation for Flask.

Flask-jsonapi is a server implementation of JSON API 1.0 specification for Flask. It allows for rapid creation of CRUD JSON API endpoints. Those endpoints can be used by JSON API clients, eg. JavaScript frontend applications written in Ember.js, React, Angular.js etc.

A compatible Python client can be found in the following package: jsonapi-request.

Flask-jsonapi depends on the following external libraries:

Features

Flask-jsonapi implements the following parts of the JSON API specification:

Not implemented yet:

Architecture

Flow through layers beginning with an HTTP Request and ending with an HTTP Response:

                                               Schema
                                                 🡙
[HTTP Request] -> [Flask Routing] -> ViewSet -> View -> Repository -> (         )
                                                                      ( Storage )
                             [HTTP Response] <- View <- Repository <- (         )
                                                 🡙
                                               Schema

Installation

To install (with SQLAlchemy support) run:

pip install Flask-jsonapi[sqlalchemy]

Simple example

Let’s create a working example of a minimal Flask application. It will expose a single resource Article as a REST endpoint with fetch/create/update/delete operations. For persistence layer, it will use an in-memory SQLite database with SQLAlchemy for storage.

Configuration

import flask
import sqlalchemy
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from marshmallow_jsonapi import Schema, fields

import flask_jsonapi
from flask_jsonapi.resource_repositories import sqlalchemy_repositories

db_engine = sqlalchemy.create_engine('sqlite:///')
session = scoped_session(sessionmaker(bind=db_engine))
Base = declarative_base()
Base.query = session.query_property()

class Article(Base):
    __tablename__ = 'articles'
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    title = sqlalchemy.Column(sqlalchemy.String)

Base.metadata.create_all(db_engine)

class ArticleRepository(sqlalchemy_repositories.SqlAlchemyModelRepository):
    model = Article
    instance_name = 'articles'
    session = session

class ArticleSchema(Schema):
    id = fields.Int()
    title = fields.Str()

    class Meta:
        type_ = 'articles'
        strict = True

class ArticleRepositoryViewSet(flask_jsonapi.resource_repository_views.ResourceRepositoryViewSet):
    schema = ArticleSchema
    repository = ArticleRepository()

app = flask.Flask(__name__)
api = flask_jsonapi.Api(app)
api.repository(ArticleRepositoryViewSet(), 'articles', '/articles/')
app.run(host='127.0.0.1', port=5000)

Usage

Create a new Article with title “First article”:

curl -H 'Content-Type: application/vnd.api+json' \
    -H 'Accept: application/vnd.api+json' \
    http://localhost:5000/articles/ \
    --data '{"data": {"attributes": {"title": "First article"}, "type": "articles"}}' \
    2>/dev/null | python -m json.tool

Result:

{
    "data": {
        "type": "articles",
        "id": 1,
        "attributes": {
            "title": "First article"
        }
    },
    "jsonapi": {
        "version": "1.0"
    }
}

Get the list of Articles:

curl -H 'Accept: application/vnd.api+json' \
    http://localhost:5000/articles/ \
    2>/dev/null | python -m json.tool

Result:

{
    "data": [
        {
            "type": "articles",
            "id": 1,
            "attributes": {
                "title": "First article"
            }
        }
    ],
    "jsonapi": {
        "version": "1.0"
    },
    "meta": {
        "count": 1
    }
}