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

Is Go Language the Right Choice for Your Next Project?

14
.
11
.
2023
Maciej Zdunek
Backend
Business

SXSW Tradeshow 2020: Get Your FREE Tickets and Meet Us

02
.
10
.
2024
Michał Krochecki
Ruby on Rails
Conferences
Frontend
Backend
Business

How to build effective website: simplicity & McDonald's

14
.
11
.
2023
Lukasz Jackiewicz
Ruby on Rails
Frontend
Design

Thermal Printer Protocols for Image and Text

14
.
11
.
2023
Burak Aybar
Backend
Tutorial
Software

WebUSB - Print Image and Text in Thermal Printers

14
.
11
.
2023
Burak Aybar
Backend
Tutorial
Software

What happened in Visuality in 2019

14
.
11
.
2023
Maciej Zdunek
Visuality
HR

Three strategies that work in board games and in real life

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails

HR Wave - No Bullshit HR Conference 2019

14
.
11
.
2023
Alicja Gruszczyk
HR
Conferences

Lightning Talks in your company

14
.
11
.
2023
Jarosław Kowalewski
Ruby on Rails
Visuality

Stress in Project Management

02
.
10
.
2024
Wiktor De Witte
HR
Project Management

How to find good developers and keep them happy - Part 1

02
.
10
.
2024
Michał Krochecki
HR
Visuality

PKP Intercity - Redesign and case study of polish national carrier

14
.
11
.
2023
Katarzyna Szewc
Design
Business
Frontend

Let’s prepare for GITEX Dubai together!

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

Ruby Quirks

14
.
11
.
2023
Jan Matusz
Ruby on Rails
Ruby

Visuality recognized as one of the Best Ruby on Rails Devs

14
.
11
.
2023
Maciej Zdunek
Ruby on Rails
Visuality
Business

Is the culture of the organization important?

14
.
11
.
2023
Alicja Gruszczyk
Conferences
Visuality

Between the devil and the deep blue sea

04
.
12
.
2023
Mateusz Wodyk
Project Management
Backend
HR

Let’s prototype!

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Backend

5 marketing hacks which will make your life easier

14
.
11
.
2023
Maciej Zdunek
Marketing
Design