Come costruire un'API REST che accetta un array di ID per le risorse


103

Sto creando un'API REST per il mio progetto. L'API per ottenere le INFO di un determinato utente è:

api.com/users/[USER-ID]

Vorrei anche consentire al cliente di passare un elenco di ID utente. Come posso costruire l'API in modo che sia RESTful e includa un elenco di ID utente?


La risposta più generica è data da @Shuja, perché altre risposte del postino non hanno funzionato e dipendono dal backend del database. Tuttavia, puoi avere un endpoint API per richiedere più ID.
Eswar

Risposte:


97

Se stai passando tutti i tuoi parametri sull'URL, probabilmente i valori separati da virgola sarebbero la scelta migliore. Quindi avresti un modello di URL come il seguente:

api.com/users?id=id1,id2,id3,id4,id5

7
@uclajatt, REST è un modello architettonico e non un protocollo e se studi le principali API REST disponibili oggi, vedrai che ci sono diversi modi per implementarlo. L'approccio che sto suggerendo è probabilmente uno dei più vicini al concetto poiché soddisfa tutti i vincoli descritti qui: en.wikipedia.org/wiki/… . Utilizzeresti solo CSV per rappresentare array nelle richieste, mentre le risposte del servizio dovrebbero essere serializzate utilizzando XML o JSON. Ci sono ragioni particolari per cui non consideri il mio approccio REST?
Florin Dumitrescu

10
Perché non questo? api.com/users?id=id1&id=id2&id=id3&id=id4&id=id5
senfo

7
@senfo, preferisco id = id1, id2, id3 perché rende l'URI più breve e più facile da leggere (da parte di un essere umano, ad esempio durante un'operazione di debug). I parametri individuali per ogni valore renderebbero l'URI particolarmente più difficile da seguire se ci sono altri parametri tra gli id: api.com/users?id=id1&id=id2&joined-after=2013-01-01&id=id3
Florin Dumitrescu

12
Tuttavia, la maggior parte dei server Web supporta la lunghezza dell'URL di circa 2.000 byte. Come fare in modo che la mia API supporti fino a 5.000 ID?
nicky_zs

6
@senfo In URL come …?id=1&id=2&id=3, non vi è alcuna garanzia che i parametri di query duplicati vengano combinati in un array. Con la stringa di query sopra, PHP ti dice che è iduguale [1, 2, 3], ma Ruby on Rails ti dice che è uguale 3, e anche altri framework possono agire in modo diverso, ad esempio dicendo iduguale 1. URL come …?id=1,2,3evitare questo potenziale di confusione.
Rory O'Kane

33
 api.com/users?id=id1,id2,id3,id4,id5
 api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

IMO, le chiamate di cui sopra non sembrano RESTful, tuttavia si tratta di una soluzione rapida ed efficiente (y). Ma la lunghezza dell'URL è limitata dal server web, ad esempio tomcat .

Tentativo RESTful:

POST http://example.com/api/batchtask

   [
    {
      method : "GET",
      headers : [..],
      url : "/users/id1"
    },
    {
      method : "GET",
      headers : [..],
      url : "/users/id2"
    }
   ]

Il server risponderà all'URI della risorsa batchtask appena creata .

201 Created
Location: "http://example.com/api/batchtask/1254"

Ora il client può recuperare la risposta batch o lo stato di avanzamento dell'attività mediante polling

GET http://example.com/api/batchtask/1254


Ecco come altri hanno tentato di risolvere questo problema:


7
La richiesta POST per ottenere più risultati non è RESTful. Il tuo esempio mostra la creazione di una risorsa, dove è appropriato POST, ma questo è un caso completamente diverso dalla domanda originale
Anentropic

2
La creazione di una risorsa temporanea è RESTful, non è vero? E sto ottenendo risorse usando GET, è di nuovo RESTful.
Nilesh

sì, ma niente di tutto ciò era nella domanda originale, che chiede solo di ottenere informazioni per più ID utente
Anentropic

1
Grazie @Anentropic per averlo segnalato. Ho letto di nuovo la domanda che chiede Come costruire un'API REST che accetta un array di ID per le risorse? e sono d'accordo, la mia risposta è diversa. Ci scusiamo per non aver capito il tuo punto.
Nilesh

Mi piace questa risposta poiché il modo RESTful per ottenere più utenti è tramite questo meccanismo.
Shane Courtrille

20

Trovo un altro modo per fare la stessa cosa usando @PathParam. Ecco il codice di esempio.

@GET
@Path("data/xml/{Ids}")
@Produces("application/xml")
public Object getData(@PathParam("zrssIds") String Ids)
{
  System.out.println("zrssIds = " + Ids);
  //Here you need to use String tokenizer to make the array from the string.
}

Chiama il servizio utilizzando il seguente URL.

http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76

dove

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76

5
Mi piace perché il GET è coerente. Puoi usare uno o più numeri in questo esempio. E non è davvero una ricerca (parametri), poiché stai dando al back-end gli ID esatti che desideri.
markthegrea

1
Vedo che la risposta più votata non funziona e la tua risposta è probabilmente la più generica. Dovrebbe essere accettato come risposta.
Eswar

18

Per quanto preferisco questo approccio: -

    api.com/users?id=id1,id2,id3,id4,id5

Il modo corretto è

    api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

o

    api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5

Ecco come fa il rack . Ecco come lo fa php . Ecco come lo fa anche node ...


19
Non sono sicuro che fare riferimento agli standard PHP come linea guida da seguire sia il miglior consiglio. eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design
trebor

Non è così che fa Flask.
jscul

0

Puoi creare un'API Rest o un progetto riposante usando ASP.NET MVC e restituire i dati come JSON. Una funzione di controller di esempio potrebbe essere:

        public JsonpResult GetUsers(string userIds)
        {
           var values = JsonConvert.DeserializeObject<List<int>>(userIds);

            var users = _userRepository.GetAllUsersByIds(userIds);

            var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
            var result = new { users = collection };

            return this.Jsonp(result);
        }
        public IQueryable<User> GetAllUsersByIds(List<int> ids)
        {
            return _db.Users.Where(c=> ids.Contains(c.Id));
        }

Quindi chiami semplicemente la funzione GetUsers tramite una normale funzione AJAX che fornisce l'array di ID (in questo caso sto usando jQuery stringify per inviare l'array come stringa e dematerializzarlo di nuovo nel controller ma puoi semplicemente inviare l'array di int e ricevere come un array di int nel controller). Ho creato un'intera API Restful utilizzando ASP.NET MVC che restituisce i dati come json tra domini e che può essere utilizzato da qualsiasi app. Ovviamente se puoi usare ASP.NET MVC.

function GetUsers()
    {
           var link = '<%= ResolveUrl("~")%>users?callback=?';
           var userIds = [];
            $('#multiselect :selected').each(function (i, selected) {
                userIds[i] = $(selected).val();
            });

            $.ajax({
                url: link,
                traditional: true,
                data: { 'userIds': JSON.stringify(userIds) },
                dataType: "jsonp",
                jsonpCallback: "refreshUsers"
            });
    }

3
Mi spiace, non stavo chiedendo come implementare l'API. Stavo solo chiedendo come costruire l'URI dell'API in modo che il client possa accedere alle informazioni su una serie di utenti. Posso passare gli ID tramite i parametri di query, ma credo che non sarà molto riposante.
uclajatt

@uclajatt Perché pensi che non sia RESTful?
Darrel Miller

1
Credo che passare gli ID o qualsiasi altro valore tramite i parametri di query sia davvero un approccio riposante per interagire con un sistema. Come ti costruisci Uri dipende da te. Essendo utenti / tutti, utenti / array, array / utenti o qualsiasi altra convenzione di denominazione, ritieni che abbia senso. Prendendo in considerazione come funziona il framework MVC, è molto facile usarlo per costruire un'API riposante poiché puoi organizzare e costruire il tuo Uris proprio come ne hai bisogno.Una volta che hai il tuo Uris, puoi passare i parametri usando AJAX come una stringa, o come valori multipli se stai usando un modulo e stai scrivendo un post in un'azione MVC.
Vasile Laur

1
@uclajatt Questo è due volte ora che ti è stato chiesto in questo post perché pensi che passare un elenco separato da virgole in un parametro di query non sia RESTful e non ti preoccupi nemmeno di rispondere, per non parlare di accettare una di queste soluzioni molto plausibili !? ! Non va bene.
samis
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.