Qual è il modo migliore per restituire un array come risposta in un'API RESTful?


41

Supponiamo di avere risorse come questa,

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

books:
    type: array
    items: book

Quindi, quando qualcuno fa una GETrisorsa sui libri, restituiremmo quanto segue

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

Ho sentito da qualcuno al lavoro che la pratica REST raccomandata è di restituire sempre le risposte come oggetti JSON, il che significherebbe che il nostro schema per bookssarebbe simile a questo,

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

Quindi, ora, la risposta sarebbe simile a questa,

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

Quale di queste è la migliore pratica REST?


1
è JSON RESTful? dovresti restituire html sicuramente?
Ewan,

3
@Ewan: il payload non ha importanza. Ecco a cosa servono i tipi MIME.
Robert Harvey,

1
Né sono le migliori pratiche per REST. REST è fatto di HATEOAS, il che significa che la tua API è rilevabile. Cerca HAL o JSON-LD.
Florian Margaine,

Json-ld: avanzando lentamente verso WCF
Ewan,

Da quello che ho letto gli avvolgimenti di array JSON all'interno di un oggetto è una misura difensiva contro una vulnerabilità segnalata nei browser più vecchi - haacked.com/archive/2009/06/25/json-hijacking.aspx . Questo sembra essere stato risolto nei browser attuali di oggi. Meglio prevenire che curare, immagino ...
Gishu,

Risposte:


35

In pratica la seconda opzione è la migliore pratica. Il motivo è che non è possibile estendere la risorsa quando si restituisce un array.

Ad esempio: se è necessario aggiungere un conteggio di tutti i record, si è già fatto con l'approccio solo matrice.

Se ciò accade in un elenco di API, si desidera mantenerlo coerente, quindi rendere tutto un oggetto quindi l'API diventa più coerente e più facile da usare per gli sviluppatori.

Ad esempio: supponiamo che uno sviluppatore scriva un codice generico per usare l'API per mostrare le pagine dell'elenco e dei dettagli. Non vuole creare un'eccezione perché a volte è un array e talvolta è un oggetto con una proprietà list.

Questa risposta in totale non ha nulla a che vedere con i principi di riposo, hateo e altri protocolli, ma solo essere reali sui dati che è necessario inviare al client. Se decidi di seguire, ad esempio, gli hateos, allora ovviamente segui i loro standard (che sono anche oggetti tra l'altro).


3
+1 per "essere reali sui dati" (e pur riconoscendo che esiste una definizione più tecnica e più accurata per REST).
tre

9

Tutti e due

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

e

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

sono validi Json. Non penso che dovresti aggiungere "list" se non è necessario, potrebbe anche essere fonte di confusione perché ciò che segue è un array, anziché un elenco.

Le migliori pratiche REST? L'API dovrebbe fornire una risposta adeguata a qualsiasi impostazione nell'intestazione Accept e anche una buona documentazione.


7

Il motivo per cui si risponde in modo conforme a JSON è che JSON è uno standard defacto; qualsiasi lingua con un parser JSON può banalmente analizzarlo e se stai usando JavaScript, non hai nemmeno bisogno di un parser poiché JavaScript lo capisce in modo nativo.

In altre parole, rendilo conforme a JSON e non dovrai scrivere il tuo parser. Inoltre, non ci saranno sorprese quando il prossimo sviluppatore scrive software che consuma il servizio.

REST non ha nulla a che fare con il tuo schema JSON. Entrambi gli schemi sono accettabili, dal punto di vista REST.


9
Questo risponde alla domanda? L'ho letto come "Dovrei usare un array json o un oggetto json come root?". Entrambi possono essere analizzati con json parser, quindi la tua risposta non li aiuta a decidere.
CodesInChaos,

Quindi non importa. Ho aggiornato la mia risposta.
Robert Harvey,

Se stiamo parlando di REST, lo schema non ha importanza fino a quando è in grado di fornire i controlli ipermediali per la scoperta e la manipolazione di ulteriori risorse basate sulla sola risposta e senza altre informazioni fuori banda ... che nessuno dei formati menzionati dall'OP sembra funzionare.
toniedzwiedz,

...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.Bene, sì e no. JSON è un sottoinsieme di JavaScript, ma chiamare evalinvece di utilizzare un parser ti rende immediatamente vulnerabile a "JSON" che contiene codice dannoso e l'analisi è molto probabilmente molto più efficiente di evalcomunque.
Doval,

5

Un dizionario con una sola chiave "list" senza senso e un valore di array è inutile: restituisce invece un array.

Se lo stesso servizio potrebbe restituire libri, CD o DVD, è possibile restituire un dizionario con una chiave "libri" e un valore di matrice. Potrebbero esserci altri "DVD" chiave con una serie di DVD. Ad esempio, se un cliente può richiedere un elenco di tutti i suoi acquisti.

Se sei certo che la risposta verrà interpretata solo come un elenco di libri (se la richiesta dicesse "dammi un elenco di libri"), allora solo un array va bene.


5

La seconda opzione è anche il metodo preferito per motivi di sicurezza. I browser meno recenti presentano una vulnerabilità di sicurezza che consente ad altro codice javascript sulla pagina Web di rubare i dati se restituiti come array JSON. Quindi storicamente la migliore pratica era di non restituire array JSON. In effetti, c'erano alcuni framework la cui funzione "json-ify" sceglie l'opzione 2 per impostazione predefinita quando si passa in un array.

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/


1

entrambi sono json e aderiscono al REST. Renderei la risposta più descrittiva, nel tuo caso cambia l'elenco in libri. O qualcosa del genere:

{ "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"}
    ]

}}
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.