Adding JSON-API to Badgeyay Backend

Badgeyay has two main components, the Python-Flask backend server and the EmberJS frontend.

EmberJS frontend uses ember data to save the data from the backend server api into the store of EmberJS frontend. To make the ember data frontend comply with backend api we need the backend server to send responses that comply with the standards of the JSON-API.

What is JSON-API?

As stated by JSONAPI.ORG

"If you've ever argued with your team about the way your JSON responses should be formatted, JSON API can be your anti-bikeshedding tool."

To put it up simply, JSON-API is a way of representing the JSON data that is being generated by the server backend. In this way we represent the JSON data in a particular way that follows the JSON-API convention. An example of data that follows json-api standards is given below:

{
"data": {
"id": "1",
"type": "posts",
"attributes": {
"title": "This is a JSON API data"
},
"relationships": {
"author": {
"links": {
"related": "/example/number"
}
},
"comments": {
"links": {
"related": "/example/number/article/"
}
"data": [
{"id": 5, "type": "example"},
{"id": 12, "type": "example"}
],
}
},
}
}

Adding JSON-API using Marshmallow-JSONAPI

We proceeded on to adding json-api into the Python-Flask backend. Before we proceed to adding json-api, we first need to install marshmallow_jsonapi

To install marshmallow_jsonapi

$ ~ pip install marshmallow-jsonapi

After installing marshmallow_jsonapi, we proceed onto making our first schema.

A schema is a layer of abstraction that is provided over a database model that can be used to dump data from or into an object. This object can therefore be used to either store in database or to dump it to the EmberJS frontend. Let us create a schema for File.

from marshmallow_jsonapi.flask import Schema
from marshmallow_jsonapi import fields


class FileSchema(Schema):
class Meta:
type_ = 'File'
self_view = 'fileUploader.get_file'
kwargs = {'id': '<id>'}

id = fields.Str(required=True, dump_only=True)
filename = fields.Str(required=True)
filetype = fields.Str(required=True)
user_id = fields.Relationship(
self_url='/api/upload/get_file',
self_url_kwargs={'file_id': '<id>'},
related_url='/user/register',
related_url_kwargs={'id': '<id>'},
include_resource_linkage=True,
type_='User'
)

So we have successfully created a Schema for getting files. This schema has an id, filename and filetype. It also has a relationship with the User.

Let us now create a route for this Schema. The below snippet of code is used to find a given file using this schema.

@router.route('/get_file', methods=['GET'])
def get_file():
input_data = request.args
file = File().query.filter_by(filename=input_data.get('filename')).first()
return jsonify(FileSchema().dump(file).data)

 

Now to get details of a file using our newly created route and schema all we need to do is use the following cURL command:

$ ~ curl -X GET "http://localhost:5000/api/upload/get_file?filename={your_file_name}"

You will get something like this as a response:

{
"data": {
"attributes": {
"filename": "13376967-8846-4c66-bcab-4a6b7d58aca7.csv",
"filetype": "csv"
},
"id": "967dc51b-289a-43a1-94c1-5cfce04b0fbf",
"links": {
"self": "/api/upload/get_file"
},
"relationships": {
"user_id": {
"data": {
"id": "J9v2LBIai1MOc8LijeLx7zWsP4I2",
"type": "User"
},
"links": {
"related": "/user/register",
"self": "/api/upload/get_file"
}
}
},
"type": "File"
},
"links": {
"self": "/api/upload/get_file"
}
}

Further Improvements

After adding JSON-API standards to the backend API we can easily integrate it with the EmberJS frontend. Now we can work on adding more schemas as a method of layers of abstraction so that the backend can serve more functionalities and the data can be consumed by the frontend as well.

Resources