npm i @dinevillar/adonis-json-api-serializer
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
getUser({request, response}) {
const user = await User.find(1);
response.send(user.toJSON());
};
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());
};
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:
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);
}
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());
}
}
const {JsonApiSerializer} = use('JsonApi');
const user = await User.find(1);
JsonApiSerializer.serialize("user", user);