Catégories
Développement informatique

Hyper­me­dia, quelques recherches pour JSON

Je regarde un peu les implé­men­ta­tions hyper­me­dia pour une API. J’avoue que je pleure un peu. Qu’on soit clairs, JSON n’est pas adapté pour ça, sauf à construire des messages bien complexes à lire et à produire (ce qui tue un peu l’uti­lité de JSON). Main­te­nant si on veut garder JSON, voilà l’état de mes reflexions :

— Ce billet est en évolu­tion constante, dernière mise à jour le 18 juin 2013 au matin —

Déjà quelques specs liées :

Et deux discus­sions à lire en amont (avec les commen­taires, pour les deux) :

JSON API

  • Spec assez simple
  • Utilise URI Template
  • Réserve un terme trop géné­rique (links) pour les clefs de la racine JSON
  • Ne permet pas d’uti­li­ser des URI pour les types de rela­tion
  • Ne permet pas d’avoir plusieurs liens (de format diffé­rent par exemple) pour une même rela­tion
  • Le type de ressource ciblée par une rela­tion peut être spéci­fié (ce qui me parait super­flu : si on connait le sens de la rela­tion, on connait le type ciblé)
  • Impose JSON-PATCH

HAL – Hyper­text Appli­ca­tion Language

  • Rendu assez moche (oui, c’est subjec­tif mais ça compte)
  • Gère des espaces de noms via Curie dans les liens et rela­tions
  • Utilise (option­nel­le­ment) les URI Template (mais ne précise pas où trou­ver les para­mètres)
  • Permet de préci­ser un profile pour quali­fier les attri­buts d’un objet (mais pas de mixer plusieurs voca­bu­laires)
  • Ne permet pas d’avoir plusieurs liens (de format diffé­rent par exemple) pour une même rela­tion
  • Beau­coup de biblio­thèques de code dans pas mal de langages, côté client et côté serveur
  • J’échoue complè­te­ment à sépa­rer ce une collec­tion ou un attri­but complexe et une ressource embarquée, donc à comprendre l’uti­lité de la clef _embed­ded
  • C’est en draft IETF

JSON-LD

  • Semble être fait par des gens avec un esprit assez proche de RDF
  • Simple à lire, mais trop complète, trop complexe, risque d’être diffi­cile à implé­men­ter
  • Gère un des voca­bu­laire avec des URI pour quali­fier les liens, les clefs, etc. avec même des possi­bi­li­tés d’alias
  • Consi­dé­rant les indi­rec­tions possibles, trou­ver le lien avec une valeur spéci­fique de « rel » est une tâche assez complexe
  • Ne gère pas de template pour les liens, mais sait gérer les liens rela­tifs à une base décla­rée plus haut (ce qui compense un peu)
  • C’est en voie de stan­dar­di­sa­tion au W3C
  • On peut ajou­ter Hydra par dessus pour décrire les actions (petite présen­ta­tion)
  • Peu d’im­plé­men­ta­tions clientes (trouvé une PHP et un conver­tis­seur vers RDF en Ruby)

Siren

  • Va plus loin que les autres, en décri­vant aussi les types d’ac­tions possibles sur la ressources décrite, les para­mètres pour les diffé­rentes actions, etc. (illu­sion de pouvoir coder un navi­ga­teur d’API géné­rique ?)
  • Pas de template pour les liens
  • Simple à comprendre et à relire (si on met de côté la partie « actions »)
  • Impose une enve­loppe, les clefs à la racine sont liées à Siren, pas à l’objet décrit
  • Pourquoi ici encore sépa­rer les enti­tés liées des proprié­tés ?

Collec­tion/JSON

Quand on pense avoir saturé, on se rend compte que ce n’est pas fini. J’ai donc trouvé Collec­tion+JSON après les autres. Il permet de défi­nit des gaba­rit d’at­tri­buts pour les ressources, ajoute les liens et les rôles des liens, la notion de collec­tion, et défi­nit les méca­nismes d’ajout/recherche.

C’est fina­le­ment une de celes qui se concentrent le mieux sur la tâche fixée au départ, mais je ne suis pas certain d’être convaincu. Au moins on a évité la sur-ingé­nie­rie. C’est implé­men­table de bout en bout.

Quelques pré-conclu­sions

Certaines spéci­fi­ca­tions vont bien trop loin à mon goût, et pas toujours en sachant faire correc­te­ment la base (éviter les conflits de nommage, pouvoir utili­ser des URI pour le voca­bu­laire, voire des espaces de noms).

Rien que les templates d’URI sont fina­le­ment inutiles. Ils permettent de grap­piller quelques octets en évitant de taper des liens complets, mais imposent de rédi­ger un code non négli­geable rien que pour recons­truire le lien final, et empêchent de copier un sous-objet en le consi­dé­rant comme auto­nome (il ne l’est pas, le template pour son URL est dans l’objet parent).

Alors parler de décrire les actions et les inter­ac­tions possibles avec chaque objet… En voulant trop en faire on reporte beau­coup de complexité sur le client. On est parfois en train de faire des clients très complexes pour éviter de gérer des infor­ma­tions simples et qu’on va proba­ble­ment de toutes façons coder en dur quelque part. Ça en devient contre-produc­tif. De ce côté j’ap­pré­cie la peti­tesse de JSON-API.

J’ai encore l’avis qu’i­ma­gi­ner un client HATEOAS complet et géné­rique est illu­soire. J’ai juste besoin d’at­ta­cher quelques méta­don­nées comme des liens, des rôles aux liens, et éven­tuel­le­ment un voca­bu­laire pour les types de données.

Et puis, sérieu­se­ment, si c’est pour que le résul­tat ne soit plus éditable agréa­ble­ment et présente des struc­tures non natu­relles, quel est l’in­té­rêt d’être passé à JSON ?

XML, ou même HTML avec des micro­data/formats est défi­ni­ti­ve­ment plus adapté que JSON pour ce que je cherche à faire. À JSON il manque au moins un moyen d’at­ta­cher des méta­don­nées à une clef/valeur (par exemple la notion d’at­tri­but sur les nœuds XML/HTML). Avec ça nous pour­rions faire un joli format, sans ça ça restera bien moche et peu pratique.

Le problème c’est que déve­lop­per un client qui fouille des données HTML avec une struc­ture lâche à base de micro­data/formats, c’est aussi assez complexe à gérer. Reste le XML « à la main » mais si si je veux que mon API soit utili­sée, je crains que JSON ne soit le seul choix prag­ma­tique.

Entre les diffé­rentes spéci­fi­ca­tions

Mon cœur balance entre JSON-API pour sa simpli­cité (mais réser­ver le terme « links » me semble juste une aber­ra­tion), HAL parce qu’il semble de loin (mais ce « _embed­ded » me gêne toujours, et faire un « _links »: { « self »: { « href »: « xxxxxx » } } juste pour donner le lien du sous-objet courant me inuti­le­ment lourd), et JSON-LD parce que ça ressemble assez fort à la façon dont je pense et que ça semble permettre tout ce que je peux imagi­ner d’in­tel­li­gent (mais implé­men­ter la spec complè­te­ment risque d’être fran­che­ment diffi­cile).

Dans une précé­dente version de ce billet j’ai tenté un subset de JSON-LD où n’im­porte quel objet peut conte­nir :

  • un attri­but (facul­ta­tif) @id, qui est le lien iden­ti­fiant l’objet
  • un attri­but (facul­ta­tif) @type, qui défi­nit l’URL du type de l’objet (par exemple un type de schema.org) et poten­tiel­le­ment le sens des sous-clefs ou sous-liens.
  • un sous-objet (facul­ta­tif) @con­text, qui contient les diffé­rents préfixes et adresses utili­sables pour les diffé­rentes clefs de l’objet (afin de pouvoir mixer plusieurs voca­bu­laires sans risquer de conflits de noms et de sens).
  • un sous-objet (facul­ta­tif) @rel, inexis­tant dans JSON-LD, qui pointe les diffé­rents objets liés par leur rôle (attri­but « rel » habi­tuel) pour les retrou­ver faci­le­ment (il y a trop d’in­di­rec­tions pour ça dans JSON-LD)

Mais je n’aime pas réin­ven­ter la roue, et aussi moche soit-il, HAL contient peut être le prin­ci­pal. Entre une spéci­fi­ca­tion géniale mais trop complexe et sans implé­men­ta­tion cliente, et une spéci­fi­ca­tion plus simple, moche mais bour­rée d’im­plé­men­ta­tions, j’ai du mal à ne pas recom­man­der la seconde. J’ai quand même toujours un peu de mal à voir comment me servir utile­ment du _embed­ded.

7 réponses sur « Hyper­me­dia, quelques recherches pour JSON »

Donc my bad. J’avais oublié JSON-LD

This document has been under development for over 25 months in the JSON for Linking Data Community Group. The document has recently been transferred to the RDF Working Group for review, improvement, and publication. The specification has undergone significant development, review, and changes during the course of the last 25 months. There are several independent interoperable implementations of this specification and a fairly complete test suite [JSON-LD-TESTS].

« On est parfois en train de faire des clients très complexes pour éviter de gérer des informations simples et qu’on va probablement de toutes façons coder en dur quelque part.  »

En même temps, le client par défaut de REST est loin d’être simple.

Alors parler de décrire les actions et les interactions possibles avec chaque objet… En voulant trop en faire on reporte beaucoup de complexité sur le client. On est parfois en train de faire des clients très complexes pour éviter de gérer des informations simples et qu’on va probablement de toutes façons coder en dur quelque part.

Ne pas reprocher à aux APIs hypermedia leur raison d’être. C’est un peu comme utiliser un robot mixeur pour battre des oeufs pour une omelette, alors qu’une simple fourchette suffit et de dire que le robot mixeur c’est très compliqué pour l’omelette. :)

Une API hypermedia a deux atouts principaux :

* Permettre de construire des clients plus robustes face à l’évolution de l’API.
* Permettre l’interopérabilité dans un marché diversifié de serveurs et de clients (penser aux sites Web)

c’est pratiquement tout. Il est tout à fait possible et valide de ne pas en avoir besoin du tout.

En première lecture ça me semble être sur le même terrain que JSON-LD, en moins complet, moins standard (JSON-LD vient de passer en REC au W3C), avec quelques conflits de noms (genre « impossible d’avoir une propriété du nom de ‘properties' »). Par contre ils utilisent la RFC6570 pour les templates d’URI, et définissent comment ça fonctionne (et ça c’est bien).

Ca mérite que j’étudie plus sérieusement mais à priori, sur ce type de structure, je trouve JSON-LD plus intéressant.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *