Quel est le meilleur moyen de renvoyer un tableau en réponse dans une API RESTful?

41

Supposons que nous avons des ressources comme celle-ci,

book:
    type: object
    properties:
        author: {type: string}
        isbn: {type: string}
        title: {type: string}

books:
    type: array
    items: book

Ainsi, lorsque quelqu'un crée une GETressource dans les livres, nous renvoyons la commande suivante.

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
 {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

Quelqu'un au travail m'a dit que la pratique REST recommandée consiste à toujours renvoyer les réponses sous forme d'objets JSON, ce qui voudrait dire que notre schéma booksressemblerait à ceci:

books:
    type: object
    properties:
        list:
            type: array
            items: book

Alors, maintenant, la réponse ressemblerait à ceci,

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
             {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

Laquelle de ces pratiques est la meilleure pratique REST?

borncrusader
la source
1
est JSON RESTful? vous devriez sûrement retourner html?
Ewan
3
@Ewan: La charge utile n'a pas d'importance. C'est à quoi servent les types MIME.
Robert Harvey
1
Ni sont les meilleures pratiques pour REST. REST est composé de HATEOAS, ce qui signifie que votre API est détectable. Recherchez HAL ou JSON-LD.
Florian Margaine
Json-ld: lentement vers la WCF
Ewan
D'après ce que j'ai lu, les tableaux JSON enveloppants à l'intérieur d'un objet constituent une mesure de défense contre une vulnérabilité signalée dans les anciens navigateurs - haacked.com/archive/2009/06/25/json-hijacking.aspx . Cela semble avoir été résolu dans les souffleurs modernes d'aujourd'hui. Mieux vaut prévenir que guérir, je suppose ..
Gishu

Réponses:

35

En pratique, la deuxième option est la meilleure pratique. La raison en est que vous ne pouvez pas étendre la ressource du tout lorsque vous venez de renvoyer un tableau.

Par exemple: Si vous devez ajouter un nombre total d'enregistrements, vous avez déjà terminé avec l'approche de type tableau uniquement.

Si cela se produit dans une API de liste, vous souhaitez la garder cohérente afin que tout soit un objet, votre API deviendra plus cohérente et plus facile à utiliser pour les développeurs.

Par exemple: supposons qu'un développeur écrit du code générique pour utiliser votre API afin d'afficher des pages de liste et de détail. Il ne veut pas créer d'exception, car il s'agit parfois d'un tableau et parfois d'un objet avec une propriété list.

Au total, cette réponse n’a rien à voir avec les principes de repos, de hateoas et d’autres protocoles, mais aussi la réalité des données que vous devez envoyer au client. Si vous décidez de suivre par exemple les hateos, tenez-vous-en à leurs normes (qui sont aussi des objets).

Luc Franken
la source
3
+1 pour "être réel à propos des données" (tout en reconnaissant qu'il existe une définition plus technique et plus précise de REST).
Threed
9

Tous les deux

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},{"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

et

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
         {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

sont valables Json. Je ne pense pas que vous devriez ajouter "list" si ce n'est pas nécessaire, cela pourrait même être déroutant, car ce qui suit est un tableau, au lieu d'une liste.

Meilleure pratique REST? L'API doit donner une réponse appropriée à tout ce qui est défini dans l'en-tête Accept, ainsi qu'une bonne documentation.

imel96
la source
7

Si vous rendez votre réponse conforme à JSON, c’est que JSON est une norme de facto; toute langue avec un analyseur JSON peut l’analyser de manière triviale, et si vous utilisez JavaScript, vous n’avez même pas besoin d’un analyseur, car JavaScript le comprend de manière native.

En d'autres termes, rendez-le compatible JSON et vous n'aurez pas à écrire votre propre analyseur. De plus, il n'y aura pas de surprises lorsque le prochain développeur écrira un logiciel consommant le service.

REST n'a rien à voir avec votre schéma JSON. Les deux schémas sont acceptables du point de vue de REST.

Robert Harvey
la source
9
Est-ce que cela répond à la question? Je l'ai lu comme "Devrais-je utiliser un tableau json ou un objet json en tant que root?". Les deux peuvent être analysés avec des analyseurs JSON, votre réponse ne les aidera donc pas à décider.
CodesInChaos
Alors ce n'est pas grave. J'ai mis à jour ma réponse.
Robert Harvey
Si nous parlons de REST, le schéma n'a pas d'importance tant qu'il est capable de fournir les commandes hypermédia pour la découverte et la manipulation de ressources supplémentaires basées sur la réponse seule et aucune autre information hors bande ... qui Aucun des formats mentionnés par le PO ne semble le faire.
toniedzwiedz
...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.Eh bien oui et non. JSON est un sous-ensemble de JavaScript mais appeler evalau lieu d'utiliser un analyseur vous rend immédiatement vulnérable à un "JSON" contenant du code malveillant, et l'analyse est très probablement beaucoup plus efficace queeval toute façon.
Doval
5

Un dictionnaire avec une seule clé sans signification "liste" et une valeur de tableau est inutile - retournez plutôt un tableau.

Si le même service peut renvoyer des livres, des CD ou des DVD, vous pouvez alors renvoyer un dictionnaire avec une clé "livres" et une valeur de tableau. Il pourrait y avoir une autre clé "DVD" avec une gamme de DVD. Par exemple, si un client peut consulter une liste de tous ses achats.

Si vous êtes certain que la réponse ne sera interprétée que comme une liste de livres (si la requête indique "donnez-moi une liste de livres"), un tableau suffit.

gnasher729
la source
5

La deuxième option est également la méthode recommandée pour des raisons de sécurité. Les anciens navigateurs présentent une vulnérabilité de sécurité qui permet à d'autres codes javascript sur la page Web de voler vos données si elles sont renvoyées sous forme de tableau JSON. Donc, historiquement, la meilleure pratique consistait à ne pas renvoyer de tableaux JSON. En fait, il y avait des frameworks dont la fonction "json-ify" choisit l'option 2 par défaut lorsque vous transmettez un tableau.

https://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk

http://ejohn.org/blog/re-securing-json/

Mandrin
la source
1

les deux sont json et adhèrent à REST. Je rendrais la réponse plus descriptive, dans votre cas, changez de liste en livres. Ou quelque chose comme ça :

{ "responceObject" : {

   results : 2,

    "Books": [
        {"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
        {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}
    ]

}}
MeganFoxObama
la source