Skip to content
An AdonisJS framework wrapper for https://github.com/danivek/json-api-serializer to have API response formatted according to the JSON API Specification (http://jsonapi.org/)
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
providers
src
.gitignore
LICENSE
README.md
instructions.js
package-lock.json
package.json

README.md

Installation

npm i @dinevillar/adonis-json-api-serializer

Setup

Create/edit config/jsonApi.js.

module.exports = {
      "globalOptions": {
          "convertCase": "snake_case",
          "unconvertCase": "camelCase"
      },
      // Register JSON API Types here..
      "registry": {
          "user": {
              "model": 'App/Models/User'
              "structure": {
                  "links": {
                      self: (data) => {
                          return '/users/' + data.id
                      }
                  },
                  "topLevelLinks": {
                      self: '/users'
                  }
              }
          }
      }
  };

Add as provider (start/app.js)

const providers = [
	'@dinevillar/adonis-json-api-serializer/providers/JsonApiProvider'
]

Add to your Models

static get Serializer() {
    return 'JsonApi/Serializer/LucidSerializer'; // Override Lucid/VanillaSerializer
};

Add as named Middleware in start/kernel.js

const namedMiddleware = {
  jsonApi: 'JsonApi/Middleware/Specification'
};

Use in your routes

// All request and response to /user must conform to JSON API v1
Route.resource('user', 'UserController')
    .middleware(['auth', 'jsonApi'])

You can use the "cn" and "ro" schemes of the middleware.

  • Adding "cn" (jsonApi:cn) will allow middleware to check for Content Negotiation
  • Adding "ro" (jsonApi:ro) will allow middleware to check if request body for POST and PATCH conforms with JSON API resource object rules
  • Adding "ro" (jsonApi:ro) also will automatically deserialize resource objects.
  • If none is specified then both will be applied

Usage

model.toJSON():

getUser({request, response}) {
  const user = await User.find(1);
  response.send(user.toJSON());
};

with relations:

config/jsonApi.js

"registry": {
	"company": {
	    "model": 'App/Models/Company',
	    "structure": {
            id: "id",
            links: {
                self: (data) => {
                  return '/companies/' + data.id
                }
            }
		}
	}
	"user": {
	    "model": 'App/Models/User',
	    "structure": {
            "links": {
                self: (data) => {
                    return '/users/' + data.id
                }
            },
            "relationships": {
                company: {
                  type: 'company',
                  links: {
                    self: '/companies'
                  }
                }
            }
            "topLevelLinks": {
                self: '/users'
            }
		}
  	}
 }

App/Models/Company

static get Serializer() {
    return 'JsonApi/Serializer/LucidSerializer';
};

App/Models/User

static get Serializer() {
    return 'JsonApi/Serializer/LucidSerializer';
};

Somewhere:

getUser({request, response}) {
  const user = await User.find(1);
  await user.load('company'); // load relation
  response.send(user.toJSON());
};

Record Browser in your Controllers

const Company = use('App/Models/Company')
const JsonApiRB = use('JsonApiRecordBrowser');
const companies = await JsonApiRB
  .model(Company)
  .request(request.get()) //handle request
  .paginateOrFetch();
response.send(companies.toJSON());

The record browser supports:

Exceptions

You can use JsonApi to handle errors and be able to return valid JSON Api error responses. Create a global ehandler using adonis make:ehandler and use JsonApi in handle() function. See examples/Exception/Handler.js

async handle(error, options) {
    JsonApi.handleError(error, options);
}

Validator

Sample Validator (see examples)

const {formatters} = use('Validator');
const JsonApi = use('JsonApi');
class UserValidator {
    get rules(){
        return {
            'username': 'required|accepted|max:255',
            'contact_number': 'required|accepted|max:50',
            'email': 'required|email|unique:companies,email|max:100'
        }
    }
    
    get formatter() {
        return formatters.JsonApi;
    }
    
    async fails({errors}) {
        for (const error of errors) {
            const jsonError = JsonApi.JSE.UnprocessableResourceObject.invoke();
            jsonError.detail = error.detail;
            jsonError.source = error.source;
            JsonApi.pushError(jsonError);
        }
        return this.ctx.response
            .status(JsonApi.getJsonErrorStatus())
            .send(JsonApi.getJsonError());
    }
}

Serializer Library:

Serializer functions

const {JsonApiSerializer} = use('JsonApi');
const user = await User.find(1);
JsonApiSerializer.serialize("user", user);
You can’t perform that action at this time.