Fév

L’univers du développement est marqué par un besoin crucial d’échanges d’informations fluides et optimisés entre applications. Au cœur de cette dynamique, JSON API se démarque en proposant une méthodologie structurée pour les interactions entre clients et serveurs au travers d’APIs RESTful basées sur JSON. Dans cet article, nous vous invitons à plonger dans les caractéristiques clés de JSON API, à évaluer ses avantages et inconvénients et à explorer un exemple concret d’interaction avec cette approche via le langage C#.

 

Une API en .NET Core

Pour explorer JSON:API, nous allons créer ensemble une application de type blog minimal avec des articles et des commentaires. Nous utiliserons .NET6.0 et les packages Nuget JsonApiDotNetCore et Microsoft.EntityFrameworkCore. Pour les besoins du test, on utilisera aussi SQLite comme base de données (package EntityFrameworkCore.SQLite). Cela va nous permettre de générer automatiquement une API fonctionnelle très rapidement.

Commençons par le modèle. Chaque classe est annotée [Resource], ce qui générera automatiquement un contrôleur associé. Les attributs [HasOne] et [HasMany] permettent de gérer très simplement les relations entre les entités.

Le DBContext est lui aussi minimal.

Ensuite on enregistre les services et le middleware lors du démarrage de l’application dans le Program.cs : 

 

Au lancement de l’application, les routes /categories/, /posts/ et /comments/ sont directement disponibles ! Nous voilà avec une API fonctionnelle.

 

JSON API vs. REST ?

JSON API, tout comme REST, repose sur les bases solides du protocole HTTP : il va décrire la manière dont les échanges de données doivent être effectués entre un client et un serveur. Là où JSON API se démarque, c’est en ajoutant une couche de conventions spécifiques en utilisant le format JSON. 

Routes et Verbes

On remarque dans le swagger de notre application qu’il n’y a pas de verbe PUT. Ce verbe permet d’écraser totalement une ressource existante en envoyant entièrement la nouvelle dans le corps de la requête. 

Le verbe PATCH permet quant à lui de ne modifier que les valeurs de certains champs d’une ressource. Celui-ci est en revanche disponible dans notre swagger.

Contrairement à REST, les modifications ne seront donc qu’incrémentales.

Le reste des verbes REST est aussi disponible dans JSON API.

Une approche standardisée

Alors que les API REST laissent souvent une marge de liberté aux développeurs pour choisir leurs propres conventions de conception, JSON API propose un ensemble cohérent de règles pour la modélisation des ressources, la gestion des erreurs … Cette approche plus cadrée est utile dans certains projets axés sur le modèle de données, comme les projets CRUD, ou exempts de tout reporting.

 

Anatomie d’une réponse

Essayons de récupérer la liste des articles en appelant simplement /posts en GET. La réponse de l’API est évidemment un objet JSON, structuré de la manière suivante :

GET /posts

Liens utiles (Links)

La section `links` de la réponse contient des liens pour naviguer entre les listes et les ressources. Par exemple, les liens `self`, `first`, `last` et `next` sont aussi utilisés pour la pagination.

GET /posts?page[size]=2&page[number]=2

Données (Data)

La section `data` de la réponse contient les données de la ressource demandée. Chaque entrée comprend les attributs (attributes), les liens liés à l’article (links) et les relations de la ressource (relationships). Cette dernière partie permet d’accéder à la catégorie et aux commentaires de l’article en question.

 

Récupération d’un Graph d’Objet

JSON API offre la possibilité de récupérer des graphiques complets d’objets en une seule requête, optimisant ainsi le processus de récupération de données. 

Dans une API REST classique, pour récupérer un article de blog, sa catégorie et ses commentaires, on a deux approches possibles : soit faire trois requêtes (une pour l’article, une pour la catégorie et une pour les commentaires), soit créer une méthode spécifique dans le contrôleur qui récupérerait le tout en un seul appel. 

JSON API propose de faire cette opération en une seule requête, de manière native : 

GET /posts?include=comments,category

On observe que la partie relationships contient maintenant les ID de la catégorie et des commentaires associés. Le détail des entités est plus bas dans un nouveau bloc `included`, juste après les blocs `links` et `data`. Tout l’intérêt de cette zone est d’éviter les doublons, par exemple si plusieurs articles appartiennent à la même catégorie, celle-ci ne sera incluse qu’une seule fois dans la partie included.

Filtrage Avancé

Le filtrage avancé de JSON API permet une extraction sélective des informations nécessaires, minimisant ainsi les données superflues dans les réponses.

Pour récupérer tous les articles dont le titre est égal à “My first post” :

GET /posts?filter=equals(title,’My first post’)

Ici les articles créés après le 1er octobre 2022 seront renvoyés :

GET /posts?filter=greaterThan(createdAt,’2022-10-01′)

Fields : Sélection de Champs

On peut n’avoir besoin que d’une partie d’un article, par exemple son titre, pour l’affichage dans une liste. L’option `fields` permet de sélectionner les champs d’une ressource à récupérer.

Cette requête renverra les titres de tous les articles :

GET /posts?fields[posts]=title

 

En combinant avec le paramètre `include`, celle-ci récupérera tous les articles, avec le champ `content` de leurs commentaires :

GET /posts?include=comments&fields[comments]=content

Opérations Transactionnelles (Bulk / Batch)

Grâce à son extension Atomic operations, JSON API prend en charge les opérations transactionnelles groupées, optimisant les performances en réduisant le nombre d’appels individuels. Cela peut être utilisé pour ajouter, modifier ou supprimer des données.

Pour utiliser cette fonctionnalité un peu plus avancée dans notre exemple, on va ajouter un contrôleur OperationsController. 

Par exemple, on peut créer une nouvelle catégorie pour l’ajouter à notre article d’id 1. Un id temporaire “lid” est utilisé au niveau de la nouvelle catégorie afin de pouvoir relier celle-ci au post qui nous intéresse. Voici le format du corps de la requête : 

POST /operations

 

NB : pour effectuer cet appel, il faut ajouter un header : 

Content-Type: application/vnd.api+json; ext= »https://jsonapi.org/ext/atomic« 

 

L’API répond avec les informations et liens de la nouvelle catégorie : 

Gestion Standardisée des Erreurs

JSON API offre une gestion standardisée des erreurs, simplifiant la compréhension et la gestion des problèmes côté client. Par exemple, lorsqu’une ressource n’est pas trouvée :

Ajout de Métadonnées

JSON API permet d’inclure des métadonnées dans les réponses d’API pour ajouter des données supplémentaires sur les ressources ou les collections envoyées, telles que des informations sur la pagination ou des statistiques. Cela peut s’effectuer de manière globale sur toutes les réponses de l’api, ou bien sur des ressources précises.

On peut vouloir ajouter un copyright à notre blog. Avec JsonApiDotNetCore, on procèdera en ajoutant une classe héritant de IResponseMeta :

Imaginons maintenant qu’on veuille ajouter l’année de création d’un article dans les métadonnées. 

On pensera bien sûr à les injecter au démarrage de l’application.

Limitations

Les librairies front

Un inconvénient de JSON API est le nombre de bibliothèques front disponibles, telles que Kitsu-core ou Ember Data (https://jsonapi.org/implementations/#client-libraries). Cette diversité peut introduire de la complexité et rendre le choix plus difficile pour les développeurs front. Aucune ne se démarque vraiment ni n’est plus maintenue qu’une autre.

 

Couplage Back / Front

JSON API peut introduire un certain niveau de couplage entre les couches backend et frontend, ce qui peut ne pas convenir à tous les projets. Par exemple, les applications effectuant beaucoup de reporting ne seront pas mises en valeur par JSON API.

 

Peu flexible

JSON API, de par sa nature très structurée, offre peu de flexibilité pour les développeurs. La customisation des appels est très limitée comme nous l’avons vu et certaines actions seront impossibles à mettre en œuvre.

 

Réponse plus verbeuse

Le corps de la réponse des requêtes peut être de taille conséquente de par la hiérarchisation des données JSON.

 

Conclusion

Pour conclure, plonger dans l’univers de JSON API, c’est s’équiper d’un outil flexible et performant pour dynamiser les échanges entre clients et serveurs. Dans le pire des cas, on pourra utiliser une JSON API côté frontend comme une API REST classique, en parsant simplement la réponse JSON, permettant de toucher un large panel d’utilisateurs, de manière peu contraignante.

 

Avec un ensemble de fonctionnalités clairement définies et standardisées, cette approche simplifie grandement la conception d’API, assurant la cohérence des interactions client serveur. La récupération optimisée de graphiques d’objets, des capacités de filtrage pointues et la prise en charge d’opérations transactionnelles groupées sont des fonctionnalités séduisantes dans la conception d’API.

 

Néanmoins, il faut rappeler que cette méthode ne convient pas à tous les scénarios. Les applications qui requièrent une séparation plus lâche entre les couches backend et frontend pourraient trouver des alternatives plus appropriées.

 

Carole CHEVALIER

Related Posts

Leave A Comment