Note: This article is a re-post from Mateu's personal blog.
I have been very vocal about the JSON:API module. I wrote articles, recorded videos, spoke at conferences, wrote extending software, and at some point, I proposed to add JSON:API into Drupal core. Then Wim and Gabe joined the JSON:API team as part of their daily job. That meant that while they took care of most of the issues in the JSON:API queue, I could attend the other API-First projects more successfully. I have not left the JSON:API project by any means, on the contrary, I'm more involved than before. However, I have just transitioned my involvement to feature design and feature sign-off, sprinkled with the occasional development. Wim and Gabe have not only been very empathic and supportive with my situation, but they have also been taking a lot of ownership of the project. JSON:API is not my baby anymore, instead we now have joint custody of our JSON:API baby.
As a result of this collaboration Gabe, Wim and I have tagged a stable release of the second version of the JSON:API module. This took a humongous amount of work, but we are very pleased with the result. This has been a long journey, and we are finally there. The JSON:API maintainers are very excited about it.
I know that switching to a new major version is always a little bit scary. You update the module and hope for the best. With major version upgrades, there is no guarantee that your use of the module is still going to work. This is unfortunate as a site owner, but including breaking changes is often the best solution for the module's maintenance and to add new features. The JSON:API maintainers are aware of this. I have gone through the process myself and I have been frustrated by it. This is why we have tried to make the upgrade process as smooth as possible.
What Changed?
If you are a long-time Drupal developer you have probably wondered how do I do this D7 thing in D8? When that happens, the best solution is to search a change record for Drupal core to see if it change since Drupal 7. The change records are a fantastic tool to track the things changed in each release. Change records allow you to only consider the issues that have user-facing changes, avoiding lots of noise of internal changes and bug fixes. In summary, they let users understand how to migrate from one version to another.
Very few contributed modules use change records. This may be because module maintainers are unaware of this feature for contrib. It could also be because maintaining a module is a big burden and manually writing change records is yet another time-consuming task. The JSON:API module has comprehensive change records on all the things you need to pay attention when upgrading to JSON:API 2.0.
As I mentioned above, if you want to understand what has changed since JSON:API 8.x-1.24 you only need to visit the change records page for JSON:API. However, I want to highlight some important changes.
Config Entity Mutation is now in JSON:API Extras
This is no longer possible only using JSON:API. This feature was removed because Entity API does a great job ensuring that access rules are respected, but the Configuration Entity API does not support validation of configuration entities yet. That means the responsibility of validation falls on the client, which has security and data integrity implications. We felt we ought to move this feature to JSON:API Extras, given that JSON:API 2.x will be added into Drupal core.
No More Custom Field Type Normalizers
This is by far the most controversial change. Even though custom normalizers for JSON:API have been strongly discouraged for a while, JSON:API 2.x will enforce that. Sites that have been in violation of the recommendation will now need to refactor to supported patterns. This was driven by the limitations of the serialization component in Symfony. In particular, we aim to make it possible to derive a consistent schema per resource type. I explained why this is important in this article.
Supported patterns are:
- Create a computed field. Note that a true computed field will be calculated on every entity load, which may be a good or a bad thing depending on the use case. You can also create stored fields that are calculated on entity presave. The linked documentation has examples for both methods.
- Write a normalizer at the Data Type level, instead of field or entity level. As a benefit, this normalizer will also work in core REST!
- Create a Field Enhancer plugin like these, using JSON:API Extras. This is the most similar pattern, it enforces you to define the schema of the enhancer.
File URLs
JSON:API pioneered the idea of having a computed url
field for file entities that an external application can use without modifications. Ever since this feature has made it into core, with some minor modifications. Now the url
is no longer a computed field, but a computed property on the uri
field.
Special Properties
The official JSON:API specification reserves the type
and id
keys. These keys cannot exist inside of the attributes
or relationships
sections of a resource object. That's why we are now prepending {entity_type}_
to the key name when those are found. In addition to that, internal fields like the entity ID (nid
, tid
, etc.) will have drupal_internal__
prepended to them. Finally, we have decided to omit the uuid
field given that it already is the resource ID.
Final Goodbye to _format
JSON:API 1.x dropped the need to have the unpopular _format
parameter in the URL. Instead, it allowed the more standard Accept: application/vnd.api+json
to be used for format negotiation. JSON:API 2.x continues this pattern. This header is now required to have cacheable 4XX error responses, which is an important performance improvement.
Benefits of Upgrading
You have seen that these changes are not very disruptive, and even when they are, it is very simple to upgrade to the new patterns. This will allow you to upgrade to the new version with relative ease. Once you've done that you will notice some immediate benefits:
- Performance improvements. Performance improved overall, but especially when using filtering, includes and sparse fieldsets. Some of those with the help of early adopters during the RC period!
- Better compatibility with JSON:API clients. That's because JSON:API 2.x also fixes several spec compliance edge case issues.
- We pledge that you'll be able to transition cleanly to JSON:API in core. This is especially important for future-proofing your sites today.
Benefits of Starting a New Project with the Old JSON:API 1.x
There are truly none. Version 2.x builds on top of 1.x so it carries all the goodness of 1.x plus all the improvements.
If you are starting a new project, you should use JSON:API 2.x.
JSON:API 2.x is what new installs of Contenta CMS will get, and remember that Contenta CMS ships with the most up-to-date recommendations in decoupled Drupal. Star the project in GitHub and keep an eye on it here, if you want.
What Comes Next?
Our highest priority at this point is the inclusion of JSON:API in Drupal core. That means that most of our efforts will be focused on responding to feedback to the core patch and making sure that it does not get stalled.
In addition to that we will likely tag JSON:API 2.1 very shortly after JSON:API 2.0. That will include:
- Binary file uploads using JSON:API.
- Support for version negotiation. Allows latest or default revision to be retrieved. Supports the Content Moderation module in core. This will be instrumental in decoupled preview systems.
Our roadmap includes:
- Full support for revisions, including accessing a history of revisions. Mutating revisions is blocked on Drupal core providing a revision access API.
- Full support for translations. That means that you will be able to create and update translations using JSON:API. That adds on top of the current ability to
GET
translated entities. - Improvements in hypermedia support. In particular, we aim to include extension points so Drupal sites can include useful related links like
add-to-cart
,view-on-web
,track-purchase
, etc. - Self-sufficient schema generation. Right now we rely on the Schemata module in order to generate schemas for the JSON:API resources. That schema is used by OpenAPI to generate documentation and the Admin UI initiative to auto-generate forms. We aim to have more reliable schemas without external dependencies.
- More performance improvements. Because JSON:API only provides an HTTP API, implementation details are free to change. This already enabled major performance improvements, but we believe it can still be significantly improved. An example is caching partial serializations.
How Can You Help?
The JSON:API project page has a list of ways you can help, but here are several specific things you can do if you would like to contribute right away:
- Write an experience report. This is a Drupal.org issue in the JSON:API queue that summarizes the things that you've done with JSON:API, what you liked, and what we can improve. You can see examples of those here. We have improved the module greatly thanks to these in the past. Help us help you!
- Help us spread the word. Tweet about this article, blog about the module, promote the JSON:API tooling in JavaScript, etc.
- Review the core patch.
- Jump into the issue queue to write documentation, propose features, author patches, review code, etc.
Photo by Sagar Patil on Unsplash.