Git Product home page Git Product logo

flask-docjson's Introduction

flask-docjson

A micro module to validate flask request and response json schemas via view function docstrings.

@app.route('/item/<id>', methods=['GET'])
@flask_docjson.validate
def get(id):
    """Get an item by id.

    Schema::

        GET /item/<i32:id>

        200
        {
            "id": i32,
            "name": string(32),
            "tags": [string, ...]
        }
    """
    pass

It's strongly recommended that you checkout example at first.

Installation

pip install flask-docjson

Usage

  • Validate routes selectively via decorator:

    @app.route('/user/<int:id>', methods=['GET'])
    @flask_docjson.validate
    def get_user(id):
        """Schema::
            ...
        """
  • Validate all routes, no need to decorate view functions one by one:

    # Must be called after all route definitions
    flask_docjson.register_all(app)

Schema

The validator only works when:

  1. Given docstring contains a marker Schema:: or Schema:.
  2. The marker is followed by a code block.

Here is an example schema:

Schema::

    POST/PUT /user
    {
        "name": string,
        "email": string,
        "class_no": i8
    }

    200
    {
        "id": i32,
        ...
    }
    4XX/5XX
    {"error": string}

A flask-docjson schema should contain one request and multiple responses descriptions, its structure:

Schema::

    <Methods> <Route>
    <Request-JSON-Schema>

    <StatusCode>
    <Response-JSON-Schema>
    ...

The first json schema is for request, and the following json schemas are for responses.

Methods contains a single or multiple http methods, e.g. DELETE, POST/PUT , all method names should in upper case. Supported method names are:

  • POST
  • GET
  • PUT
  • DELETE
  • PATCH
  • HEAD
  • OPTIONS

Route is a flask url rule, but supports stricter variable types. e.g. /user/<i32:id>, /name/<string(32):name>. Note that these types are validators but not converters. We still need to use flask built-in converters:

@app.route("/<int:id>", methods=['GET'])  # OK
# @app.route("/<id>", methods=['GET'])  # BAD
def get(id):
    """Schema::

        GET /<i32:id>
        200
     """

JSON-Schema has json like structure, it may be an array of type definitions, or an object of key-type pairs. And both array and object are also types. Some examples:

  • [u8, u16, u32] (array of base types)
  • {"text": string(255), "id": i32} (object of base types)
  • [{"key": i16}, ...] (array of objects)
  • {"key": [u32, ...]} (object with array values)
  • [u32, ...] (also called ellipsis array)
  • {"id": i32, ...} (also called ellipsis object)

StatusCode contains a single or multiple status codes, e.g. 204/200. What's more, status code matcher like 4XX, 5XX are also supported.

In standard JSON, schema with a trailing comma (e.g. {"key": "value",}) is illegal, but our JSON schema allows this. Because that makes modifications by line convenient.

Base Types

  • Boolean: bool
  • Number: u8, u16, u32, u64, i8, i16, i32, i64, float
  • String: string, string(maxlength) (e.g. string(32))

Container Types

  • Array: e.g. [u8, i32, string], [u8, ...].
  • Object: e.g. {"name": string(32)}, {"id": i32, ...}.

Ellipsis Array

An array definition with ellipsis is called "ellipsis array", for an example:

{
    "item": [u8, ...]
}
  1. Empty list (aka []) is able to pass ellipsis array validation.
  2. For this example, all elements in given items should be an u8.

Ellipsis Object

An object definition with ellipsis is called "ellipsis object", for an example:

{
    "id": i32,
    ...
}
  1. An ellipsis object indicates given object value may contain more fields, but docjson won't (also can't) validate them.
  2. For a non-ellipsis object definition, given object value shouldn't contain any keys that dosen't exist in the type definition.

Nullable Value

By default, values shouldn't be nullable and None value causes validation error. An example to change this behavior is:

{
    "optional-string": string(32)*,
    "optional-integer": i32*
}

And, nullable values are optional in objects, key not exists error won't throw.

But note that * can't be used with the whole request/response json schema, that is to say schemas like the following definition are illegal:

GET /

200
{
    "name": string
}*

No Content

Some requests or responses have no content, we just leave the json schema blank:

  • Request schema without content example:

    GET /data
    200
    {"key": float}
    
  • Response schema without content example:

    DELETE /data/<i32:id>
    204
    

Comments

We may want to comment on some json fields:

PUT /order
{
    "price": float, // precision:10, scale:2
}

200
{
    "id": i32,
     ...
}

Exceptions

  • flask_docjson.Error: Raised when a flask-docjson error occurred.
  • flask_docjson.ParserError: Raised when a parser error occurred.
  • flask_docjson.LexerError: Raised when a lexer error (e.g. bad token) occurred.
  • flask_docjson.GrammarError: Raised when a grammar error occurred.
  • flask_docjson.ValidationError: Raised when some request or response data is invalid.
  • flask_docjson.RequestValidationError: Raised some when request data is invalid.
  • flask_docjson.ResponseValidationError: Raised some when response data is invalid.

Error is the base exception. ParserError only occurrs on flask app bootstrap, it won't be raised during processing requests.

ValidationError should be catched manually, we recommend to use the flask built-in decorator app.errorhandler. And we can also get code, reason and related value from a ValidationError instance:

@app.errorhandler(flask_docjson.ValidationError)
def on_validatino_error(err):
    return jsonify(message='Validation error:{0} {1} on {2}'.format(err.code, err.reason, err.value)), 400

Language Description

  • Document: Schema ::= Request Response*.
  • Request: Request ::= Method* Route JsonSchema
  • Response: Response ::= StatusCode* JsonSchema
  • Method: Method ::= POST|PUT|GET|DELETE|PATCH|HEAD|OPTIONS. Method separator is /.
  • Route: Route ::= StaticRoute* RouteVar* StaticRoute*. e.g. /user/<i32:id>
  • StatusCode: StatusCode ::= Integer|Matcher. e.g. 200, 4XX
  • JsonSchema: JsonSchema ::= Array | Object.
  • Array: Array ::= '[' Value* | Value* '...' ']'
  • Object: Object ::= '{' KeyValue* '}'
  • KeyValue: KeyValue ::= Key ':' Value
  • Value: Array ::= BaseType | Array | Object

License

BSD.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.