Progettazione dell'API RESTful. Cosa devo restituire se non ci sono righe?

50

Attualmente sto codificando un'API per un social network con Slim Framework. La mia domanda è: quali sono le migliori pratiche quando non ci sono righe da restituire nella struttura JSON?

Diciamo che questa chiamata / v1 / get / movies restituisce 2 righe dai nomi dei film della tabella:

[
    {"name": "Ghostbusters"},
    {"name": "Indiana Jones"}
]

Ma poi chiamo / v1 / get / books e non ci sono righe in quella tabella. Devo restituire una struttura vuota?

[
]

... o sarebbe meglio un messaggio e un codice di errore?

[
    "errors": {
        "message": "no matches found",
        "code": 134
    }
]

Quale è una pratica migliore? (l'API verrà utilizzata nelle app iOS e Android) Grazie!

    
posta Andres SK 29.05.2013 - 08:09
fonte

14 risposte

45

Di solito restituirei il numero di record nel risultato come metadati. Non sono sicuro che si tratti di una normale pratica di REST, ma non sono molti dati extra, ed è molto precisa. Di solito c'è una paginazione per molti servizi, non è pratico restituire enormi risultati contemporaneamente. Personalmente sono seccato quando c'è impaginazione per piccoli set di risultati .. Se è vuoto, restituisce number_of_records : 0 e libri come elenco vuoto / matrice books : [] .

{
    meta: {
        number_of_records : 2,
        records_per_page : 10,
        page : 0
    },
    books : [
        {id:1},
        {id:27}
    ]
}

EDIT (pochi anni dopo): La risposta di Martin Wickman è molto migliore, ecco "breve" spiegazione del perché.

Quando si ha a che fare con l'impaginazione, tenere sempre presente la possibilità che il contenuto o l'ordine cambino. Come, la prima richiesta arriva, 24 risultati, si ritorna prima 10. Dopo di ciò, viene inserito "nuovo libro" e ora si hanno 25 risultati, ma con la richiesta originale verrebbe ordinato al 10 ° posto. Quando il primo utente richiede la seconda pagina, non otterrebbe il "nuovo libro". Ci sono modi per gestire tali problemi, come fornire "ID richiesta" che dovrebbe essere inviato con le seguenti chiamate API, quindi restituire la prossima pagina dal "vecchio" set di risultati, che dovrebbe essere memorizzato in qualche modo e legato a "ID richiesta". Alternativa è aggiungere campi come "lista dei risultati modificata dalla prima richiesta".

Generalmente, se puoi, cerca di fare uno sforzo extra ed evitare l'impaginazione. La paginazione è uno stato aggiuntivo che può essere mutato e il monitoraggio di tali modifiche è soggetto a errori, anche perché sia il server che il client devono gestirlo.

Se hai troppi dati da elaborare in una sola volta , considera la possibilità di restituire "id list" con tutti i risultati e i dettagli per alcune porzioni di quell'elenco e fornire chiamate API multi_get / get_by_id_list per la risorsa.

    
risposta data 29.05.2013 - 08:52
fonte
105

Il tuo esempio è rotto. Non dovresti avere oggetti JSON con chiavi duplicate. Quello che stai cercando è un array con oggetti film, come questo:

 [
    {"name": "movie1"}, 
    {"name": "movie2"}
 ]

Questo approccio risponde anche alla tua domanda. Dovresti restituire un array vuoto quando la query non corrisponde:

[]

D'altra parte, se provi a ottenere una risorsa video specifica con GET api/movie/34 e quel film non esiste, quindi restituisci 404 con un messaggio di errore adatto (json codificato) nel corpo

    
risposta data 29.05.2013 - 10:27
fonte
15

Se questo è JSON, dovresti davvero considerare di restituire una Matrice di oggetti. Questo ha molti vantaggi tra cui quello in cui non ci sono record è un array vuoto.

Quindi, quando hai dei record, verrebbe restituito:

    [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]

E quando non hai record, verrai restituito:

    [

    ]
    
risposta data 29.05.2013 - 09:10
fonte
14

Se si esegue l'operazione con successo, ma non ha nulla da restituire, come ad esempio la mappa vuota {} o l'array vuoto [] Preferirei rispondere con un codice di risposta 204, qui è estratto da Definizioni dei codici di stato HTT specifica:

The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.

If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view.

The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

In sostanza, raccomando di usare 204 in applicazioni RESTful su HTTP quando non c'è nulla da restituire.

    
risposta data 29.05.2013 - 14:01
fonte
10

C'è stato un ragionevole lavoro svolto sulla creazione di un formato API JSON standardizzato .

Seguendo i principi di questa specifica significa che tutte le risorse restituite dovrebbero essere effettivamente "raccolte" (anche quando è inclusa una sola risorsa). In seguito ciò significherebbe che la tua chiamata a /v1/get/movies restituirebbe:

{
    "movies": [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]
}

La tua chiamata a /v1/get/books (che restituisce zero risorse) restituirebbe:

{
    "books": []
}
    
risposta data 29.05.2013 - 19:44
fonte
5

Per il tuo esempio specifico, ti consiglio che / v1 / get / books restituisca l'HTTP 200 con un array vuoto.

Se sto leggendo il tuo post, la tua API intende raccogliere libri. Metaforicamente parlando, hai una libreria per libri, un rack DVD per film e forse altri contenitori che non hai menzionato qui. Perché hai intenzione di raccogliere libri, / v1 / get / books è la tua libreria. Questo significa che c'è una risorsa valida - una lista di libri - che risulta essere vuota nel tuo esempio specifico.

Il motivo per cui non suggerisco di restituire HTTP 404 in questo caso è che lo scaffale sia ancora lì. Al momento non ci sono libri, ma è ancora una libreria. Se non fosse un bookshelf, se l'API non intendeva raccogliere libri, ad esempio- allora HTTP 404 sarebbe appropriato. Ma poiché c'è una risorsa lì, non dovresti segnalare che non ce n'è uno, quale HTTP 404 fa. Pertanto, sostengo che 200 con un array vuoto (che indica la raccolta) è più appropriato.

Il motivo per cui non suggerisco di restituire HTTP 204 è che questo suggerirebbe che "Nessun contenuto" è lo stato ordinario delle cose: eseguire questa azione su questa risorsa normalmente non restituirebbe nulla. Ecco perché viene solitamente utilizzato come risposta alle richieste DELETE, ad esempio: la natura dell'eliminazione generalmente significa che non viene lasciato nulla da restituire. Il caso è simile quando è usato per rispondere alle richieste con la famiglia di intestazioni If-Modified: volevi solo contenuto se la risorsa era cambiata, ma non lo era, quindi non ti darò alcun contenuto.

Ma sostengo che per GETting di una raccolta vuota ma valida, HTTP 204 non ha senso. Se ci fossero elementi nella collezione, la rappresentazione corretta sarebbe una matrice di quei dati. Pertanto, quando non ci sono dati lì (ma la raccolta è valida), la rappresentazione corretta è una matrice vuota.

    
risposta data 06.02.2014 - 20:14
fonte
5

Dovresti davvero fare solo una delle due cose

In entrambi i Restituisce un codice di stato 200 (OK) e un array vuoto nel corpo.

O Restituisce un codice di stato 204 (NO CONTENT) e un corpo di risposta NO.

Per me, l'opzione 2 sembra più tecnicamente corretta e in linea con i principi REST e HTTP.

Tuttavia, l'opzione 1 sembra più efficiente per il client, perché il client non ha bisogno di logica aggiuntiva per distinguere tra due (successi) codici di stato. Poiché sa che riceverà sempre un array, deve semplicemente verificare se non ha ricevuto nessuno, uno o più elementi e elaborarlo in modo appropriato

    
risposta data 29.09.2014 - 18:48
fonte
3

Ho visto entrambi i casi negli ambienti di produzione. Quale sceglierai dipende da chi utilizzerà l'API. Se vogliono sapere perché l'elenco è vuoto o per essere sicuri che la lista sia veramente vuota e non si siano verificati errori durante il recupero, è necessario allegare un oggetto "errori". Se non gli interessa, vai con la restituzione di una lista vuota. Vorrei seguire il secondo approccio poiché copre più esigenze rispetto al primo.

    
risposta data 29.05.2013 - 08:49
fonte
3

La prima cosa da considerare, dal momento che stai creando un'API RESTful, è di restituire un codice di risposta appropriato. E il codice di risposta più appropriato per comunicare che la richiesta è passata normalmente, ma la risorsa richiesta non è disponibile al momento è la venerabile 404.

Se si progetta la propria API in modo tale da restituire sempre un codice di risposta ragionevole, potrebbe non essere nemmeno necessario restituire un corpo quando la risorsa non è stata trovata. Detto questo, restituire un corpo, specialmente leggibile da un punto di vista umano, non può ferire.

Non ci sono "best practice" qui, entrambi gli esempi sono arbitrari, basta sceglierne uno e essere coerenti . Gli sviluppatori odiano le sorprese, se /v1/get/movies restituisce {} quando non ci sono film allora ci aspettiamo che /v1/get/actors restituisca anche {} quando non ci sono attori.

    
risposta data 29.05.2013 - 08:49
fonte
1

Non credo che la risposta giusta sia quella contrassegnata.

La risposta fornita da nirth dovrebbe essere la migliore, in un vero scenario REST. La risposta del corpo dovrebbe essere vuota e il codice di stato http: 204; la risorsa esiste ma ha "nessun contenuto" in quel momento: è vuota.

REST HTTP_Status_Codes

    
risposta data 04.06.2013 - 11:32
fonte
1

Raccomando 200 + array vuoto, poiché semplifica la gestione da parte di tutti i client dell'API. 200 + array significa "Ho restituito tutti i dati che ci sono". Sia per il codice che consegna i dati sia per il codice che lo elabora, il numero di elementi sarebbe irrilevante.

Ogni altro codice di stato deve essere adeguatamente documentato e correttamente consegnato dal server e correttamente elaborato dal client, e sappiamo tutti quanto è probabile che ciò accada.

C'era un suggerimento per restituire lo stato 204 + corpo vuoto. Ciò significa che costringi ogni singolo client a elaborare correttamente lo stato 204. Inoltre li costringi a gestire le risposte non JSON! Spero che tutti si rendano conto che solo perché una richiesta ha ricevuto una risposta, ciò non significa che la risposta proviene dal server quando si utilizza HTTP, e solo un controllo che la risposta sia JSON gestisce molti di questi casi.

    
risposta data 22.11.2015 - 14:57
fonte
0

Vorrei "Dipende".

Se zero è un risultato ragionevole, restituire la lista vuota. Ad esempio, se si desidera ottenere tutti i dipendenti chiamati "bob" dove "nessuno" è un risultato abbastanza ragionevole. Se non è un risultato atteso, restituisce un errore. Ad esempio, ottenere una lista storica di indirizzi stradali per una persona che impieghi. Devono vivere da qualche parte quindi nessun risultato è probabilmente un errore, non solo una condizione normale.

Sono sicuro che puoi discutere con le specifiche del mio esempio, ma ti viene l'idea ...

    
risposta data 06.02.2014 - 13:58
fonte
0
  • Prima di tutto, avere get nel tuo URL non è RESTful, GET è implicito dal metodo HTTP.
  • Se stai richiedendo una raccolta come GET api/movies restituisci 200 OK con un array vuoto [] .
  • Se stai richiedendo un film specifico come GET api/movies/1 (dove 1 è l'ID) e non esiste, restituisci 404 Not Found .

Perché? Stai richiedendo risorse . Quando si richiede la raccolta, esiste la risorsa stessa (la raccolta). Pertanto, un 404 è sbagliato. Ma se richiedi un film specifico e non esiste, la risorsa richiesta non esiste e devi restituire un 404 .

    
risposta data 22.11.2015 - 13:35
fonte
-2

Se stai restituendo JSON, è meglio restituire sempre il conteggio e il messaggio di errore e forse un booleano che indica se c'è un errore o no, cioè i miei tre valori meta standard restituiti con ogni elenco di righe.

    
risposta data 22.11.2015 - 15:12
fonte

Leggi altre domande sui tag