14
.
11
.
2023
7
.
05
.
2019
Ruby on Rails
Backend
Tutorial

JSON:API consumption in Rails

Jan Matusz
Ruby Developer

In the world of modern web applications you cannot avoid becoming a heavy user of APIs. Consumption of different interfaces brings the experience, and experience brings knowledge.

One of the many things we learned at Visuality is that its not only okay to try new things, but it is also even better if other people tried these and have some insights on how to actually do it the good way. Over time we researched and developed ways to introduce JSON:API into our Rails applications, so that we could be compliant with this specification, thanks to which the development process would be more effective and time efficient.

If you would like to learn more about JSON:API consider checking out Nadia's article about JSON:API and NIH syndrome.

Let's get down to business now, and as a backend engineer at Visuality, I will be your guide today!

Shortcoming

There are many implementations of this standard (you can find a comprehensive list here), but what we recognised is that most of them usually work one-way: to serialise the data we have in the Rails application so it can be served to the API consumer. The major shortcoming was that there was no go-to solution for receiving and understanding the input the consumer sends to our application.

The ones that supposedly were to support input deserialisation either did not work 100%, were abandonware or weren't supporting JSON:API specification in its entirety.

It was a dead end.

Innovation

It lead us to a point where we decided that maybe it is a good idea to create something of our own. We had a simple goal: our Rails application must read JSON:API compliant input and handle it. It would be the best if it did not require huge configuration overhead and if it didn't force people to learn and write code in a very different (compared to what is acknowledged as standard, Rails-way) convention.

The input that JSON:API specification describes is pretty simple. Take a look at a sample:

POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "data": {
    "type": "photos",
    "attributes": {
      "title": "Ember Hamster",
      "src": "http://example.com/images/productivity.png"
    },
    "relationships": {
      "photographer": {
        "data": { "type": "people", "id": "9" }
      }
    }
  }
}

Lets break down and note a few things:

  • Content-Type --- JSON:API has its own mime type registered: application/vnd.api+json, and specification requires all requests to provide it,
  • Request body. We can see that the main key is data, which holds resources informations.
  • Resource --- it is identified by a type, attributes and optional relationships(which, again, are resources).

This input will not work with what you would typically write inside a Rails controller to handle parameters. Instead, this is how it would look like:

{
 "photo_parameters": {
  "title": "Ember Hamster",
  "src": "http://example.com/images/productivity.png",
  "photographer": { "id": 9 }
 }
}

For a person that had been working with Rails over the years, but not with JSON:API, I would not be surprised if you were in favour of the latter example. However, JSON:API provides lots of great functionalities and features that would not be so easy to achieve on your own (and then, you would have to educate your consumers on how to use these).

At Visuality the choice was made that JSON:API is the way we want to go for now --- as it was either that, or the implemented-here solutions that varied in features between different projects. JSON:API gave us a good, unified solution that had every scenario that we needed. Returning data in this format was easy, as you had ActiveModelSerializers or fast_jsonapi from Netflix, but there was no way to easily understand the input client would send us.\ But since we already could compare the JSON:API compliant input and the Rails expected one, why not get the best out of two worlds? Why should not we let Rails developers keep using their parameters as they always had done, while allowing JSON:API consumers to actually consume and feed the server with JSON:API data?

JsonApi::Parameters

That is why we brought a new library to life. Our gem aims to support Rails developers in consuming JSON:API input. It is mostly just a translator, that transforms standard compliant input to what Rails (and Rails developers) expect. Considering a sample params call in a controller:

params.require(:photo).permit(photographer: [:id])

The only thing you need to consume the JSON:API version of it is prepend require with from_jsonapi:

params.from_jsonapi.require(:photo).permit(photographer: [:id])

What this function does is literally translating the JSON:API input into a new instance of ActionController::Parameters that has a form of standard Rails model parameters.\ The specification has things that may be considered quirks, especially when it comes to creating new related resources --- where you have relationships key, and included key (one holds the resource identifier and its type, second holds the resources attributes object). We have done our best to handle these as well.

We did not want to limit our users to Rails only, so you can also use this gem in vanilla Ruby.

Additionally, if you remember from the things we have noted down above, there was this specific JSON:API Content-Type. JsonApi::Parametersregisters this mime type for you, in a way that should not break your Rails app (obviously you can unregister the Mime Type yourself, if you would like to).

So far we have been using this library in production for a couple of months now and it has proven handy, so we are looking forward to maintain and extend it. Actually, we have already had a couple of feature requests (one being the Mime::Type registration process) that we were happy to handle and implement, so definitely share your insights with us in the Github repository!

If you're interested in more blog posts like this please visit our Visuality Blogor our Medium Page

Resources

Thanks to Grzegorz Korzeniowski.

Jan Matusz
Ruby Developer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

WebUSB - Bridge between USB devices and web browsers

14
.
11
.
2023
Burak Aybar
Ruby on Rails
Frontend
Backend
Tutorial

Visuality comes to town - this time it's Poznań

14
.
11
.
2023
Michał Piórkowski
Visuality
HR

CSS Modules in Rails

14
.
11
.
2023
Adam Król
Ruby on Rails
Tutorial
Backend
Frontend

How to choose a software house.

14
.
11
.
2023
Michał Piórkowski
Ruby on Rails
Business
Visuality

JSON API versus the NIH syndrome

14
.
11
.
2023
Nadia Miętkiewicz
Backend
Frontend
Tutorial

From Idea to Concept

02
.
10
.
2024
Michał Krochecki
Ruby on Rails
Business
Startups

Styling React Components

14
.
11
.
2023
Umit Naimian
Ruby on Rails
Frontend
Tutorial

How good design can help your business grow

14
.
11
.
2023
Lukasz Jackiewicz
Design
Business
Marketing

TODO not. Do, or do not.

29
.
11
.
2023
Stanisław Zawadzki
Ruby on Rails
Software

CS Lessons #003: Density map in three ways

14
.
11
.
2023
Michał Młoźniak
Ruby
Backend
Tutorial
Software

Clean code for the win

14
.
11
.
2023
Michał Piórkowski
Ruby on Rails
Backend
Frontend
Business

Crowd-operated Christmas Lights

14
.
11
.
2023
Nadia Miętkiewicz
Ruby on Rails
Backend

How to startup and be mature about it

14
.
11
.
2023
Rafał Maliszewski
Ruby on Rails
Startups
Business

A journey of a thousand miles begins with workshops

14
.
11
.
2023
Michał Piórkowski
Software
HR

CS Lessons #002: Data structures

14
.
11
.
2023
Michał Młoźniak
Ruby
Software

Summary of Phoenix workshop at Visuality

14
.
11
.
2023
Karol Słuszniak
Ruby on Rails
Visuality
Backend

CS Lessons #000: Introduction and motivation

14
.
11
.
2023
Michał Młoźniak
Ruby
Software

CS Lessons #001: Working with binary files

14
.
11
.
2023
Michał Młoźniak
Ruby
Software

Working with 40-minute intervals

14
.
11
.
2023
Sakir Temel
Software
HR

THE MATURE TECH STARTUP DILEMMA: WHAT'S NEXT

14
.
11
.
2023
Susanna Romantsova
Startups

Win MVP workshop!

14
.
11
.
2023
Susanna Romantsova
Startups

FINTECH WEEK IN OSLO: WHATs & WHYs

14
.
11
.
2023
Susanna Romantsova
Conferences

MY FIRST MONTH AT VISUALITY

14
.
11
.
2023
Susanna Romantsova
Visuality
HR

NASA 1st global hackaton in Poland? Visuality Created it!

14
.
11
.
2023
Rafał Maliszewski
Ruby on Rails

Berlin StartupCamp 2016 summary

14
.
11
.
2023
Michał Piórkowski
Conferences
Startups