115 votes

Charge utile de réponse de pagination à partir d'une API RESTful

Je veux le soutien de la pagination dans mon API RESTful.

Mon API méthode doit retourner un JSON liste de produits par /products/index. Cependant, il y a potentiellement des milliers de produits, et je veux à la page grâce à eux, donc, ma demande doit ressembler à ceci:

/products/index?page_number=5&page_size=20

Mais en quoi ma réponse JSON besoin de ressembler? Serait API habituellement, les consommateurs attendent de la pagination des méta-données dans la réponse? Ou est seulement une gamme de produits nécessaires? Pourquoi?

Il ressemble à l'API Twitter inclut des métadonnées: https://dev.twitter.com/docs/api/1/get/lists/members (voir Exemple de Demande).

Avec des méta-données:

{
  "page_number": 5,
  "page_size": 20,
  "total_record_count": 521,
  "records": [
    {
      "id": 1,
      "name": "Widget #1"
    },
    {
      "id": 2,
      "name": "Widget #2"
    },
    {
      "id": 3,
      "name": "Widget #3"
    }
  ]
}

Juste une gamme de produits (pas de méta-données):

[
  {
    "id": 1,
    "name": "Widget #1"
  },
  {
    "id": 2,
    "name": "Widget #2"
  },
  {
    "id": 3,
    "name": "Widget #3"
  }
]

145voto

codeprogression Points 1563

ReSTful Api sont consommés principalement par les autres systèmes, c'est pourquoi j'ai mis la pagination des données dans les en-têtes de réponse. Cependant, certaines API, les consommateurs ne peuvent pas avoir un accès direct pour les en-têtes de réponse, ou peut-être la construction d'un UX au-dessus de votre API, ainsi qu'en fournissant un moyen de récupérer (sur demande) les métadonnées dans la réponse JSON est un plus.

Je crois que votre mise en œuvre devrait inclure lisibles à la machine de métadonnées par défaut, et lisible par l'homme, les métadonnées lors de la demande. L'lisible par l'homme, les métadonnées peuvent être retournés avec à chaque demande, si vous le souhaitez, ou, de préférence, à la demande via un paramètre de requête, comme include=metadata ou include_metadata=true.

Dans votre scénario, je dirais l'URI pour chaque produit avec l'enregistrement. Cela rend plus facile pour les API des consommateurs pour créer des liens vers les produits individuels. Je voudrais également mettre quelques attentes raisonnables que par les limites de ma pagination à la demande. La mise en œuvre et documenter les paramètres par défaut pour la taille de la page est une pratique acceptable. Par exemple, GitHub de l'API définit la taille de page par défaut de 30 enregistrements avec un maximum de 100, plus fixe un taux limite sur le nombre de fois où vous pouvez interroger l'API. Si votre API a une taille de page par défaut, puis la chaîne de requête pouvez simplement spécifier l'index de la page.

Dans le lisible par l'homme, scénario, lors de la navigation à l' /products?page=5&per_page=20&include=metadata, la réponse pourrait être:

{
  "_metadata": 
  {
      "page": 5,
      "per_page": 20,
      "page_count": 20,
      "total_count": 521,
      "Links": [
        {"self": "/products?page=5&per_page=20"},
        {"first": "/products?page=0&per_page=20"},
        {"previous": "/products?page=4&per_page=20"},
        {"next": "/products?page=6&per_page=20"},
        {"last": "/products?page=26&per_page=20"},
      ]
  },
  "records": [
    {
      "id": 1,
      "name": "Widget #1",
      "uri": "/products/1"
    },
    {
      "id": 2,
      "name": "Widget #2",
      "uri": "/products/2"
    },
    {
      "id": 3,
      "name": "Widget #3",
      "uri": "/products/3"
    }
  ]
}

Lisibles par machine pour les métadonnées, j'ajouterai le Lien en-têtes de la réponse:

Link: </products?page=5&perPage=20>;rel=self,</products?page=0&perPage=20>;rel=first,</products?page=4&perPage=20>;rel=previous,</products?page=6&perPage=20>;rel=next,</products?page=26&perPage=20>;rel=last

(le Lien valeur d'en-tête doit être urlencoded)

...et peut-être une coutume total-count - tête de réponse, si vous le souhaitez:

total-count: 521

L'autre pagination des données a révélé dans l'homme centrée sur les métadonnées peuvent être superflu, pour la machine, centrée sur les métadonnées, ainsi que le lien des en-têtes laissez-moi savoir à quelle page je suis sur et le nombre par page, et je peux rapidement récupérer le nombre d'enregistrements dans le tableau. Donc, je serais probablement seulement créer un en-tête pour le nombre total. Vous pouvez toujours changer d'avis plus tard et en rajouter.

En passant, vous remarquerez peut-être que j'ai supprimé /index de votre URI. Généralement, la convention est d'avoir votre point de terminaison ReST exposer des collections. Ayant /index à la fin brouille que légèrement.

Ce sont juste quelques choses, je tiens à avoir lors de la consommation d'/création d'une API. Espérons que ça aide!

35voto

Majix Points 299

Comme quelqu'un qui a écrit plusieurs bibliothèques pour consommer des services REST, permettez-moi de vous donner le point de vue du client sur pourquoi je pense que l'emballage de la suite dans les métadonnées est le chemin à parcourir:

  • Sans compter, comment le client peut-il savoir qu'il n'a pas encore reçu tout ce qu'il est, et devrait continuer d'échange à l'ensemble de résultat? Dans une INTERFACE utilisateur qui n'effectue pas de regarder en avant à la page suivante, dans le pire des cas cela peut être représenté comme un/Suivant lien de Plus qui n'a pas fait de récupérer plus de données.
  • Y compris les métadonnées dans la réponse permet au client de suivre moins de l'état. Maintenant, je n'ai pas à correspondre à ma demande RESTE de la réponse, la réponse contient les métadonnées nécessaires pour reconstruire la demande de l'etat (dans ce cas, le curseur dans le jeu de données).
  • Si l'état est une partie de la réponse, je peux effectuer plusieurs requêtes dans le même ensemble de données simultanément, et je peux traiter les demandes dans l'ordre de leur arrive d'arriver dans ce qui n'est pas nécessairement l'ordre j'ai fait la demande.

Et une suggestion: à l'Instar de l' API Twitter, vous devez remplacer le page_number avec un droit d'index/curseur. La raison en est, l'API permet au client de définir la taille de page par demande. Est le retour de l'page_number le nombre de pages que le client a demandé jusqu'à présent, ou le numéro de la page donnée, la dernière page_size (presque certainement le plus tard, mais pourquoi ne pas éviter cette ambiguïté en tout)?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X