Qual é a melhor maneira de retornar uma matriz como resposta em uma API RESTful?


41

Suponha que temos recursos como este,

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

books:
    type: array
    items: book

Portanto, quando alguém cria um GETrecurso sobre os livros, retornaríamos o seguinte

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

Ouvi de alguém no trabalho que a prática REST recomendada é sempre retornar respostas como objetos JSON, o que significaria que nosso esquema booksseria assim,

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

Então, agora, a resposta seria assim,

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

Qual dessas é a melhor prática de REST?


1
JSON é RESTful? você deve retornar html com certeza?
Ewan

3
@ Ewan: A carga útil não importa. É para isso que servem os tipos MIME.
Robert Harvey

1
Nem são as melhores práticas para o REST. O REST é feito com HATEOAS, o que significa descoberta da sua API. Procure HAL ou JSON-LD.
Florian Margaine

JSON-LD: trabalhar o seu caminho lentamente em direção WCF
Ewan

Pelo que li, as matrizes JSON empacotadas dentro de um objeto são uma medida defensiva contra uma vulnerabilidade relatada em navegadores mais antigos - haacked.com/archive/2009/06/06/25/json-hijacking.aspx . Isso parece ter sido corrigido nos navegadores modernos de hoje. É melhor prevenir do que remediar, eu acho .. #
394

Respostas:


35

Na prática, a segunda opção é a melhor prática. A razão para isso é que você não pode estender o recurso quando você apenas retorna uma matriz.

Por exemplo: Se você precisar adicionar uma contagem de todos os registros, você já fez a abordagem somente de matriz.

Se isso acontecer em uma lista de APIs, então você deseja mantê-lo consistente, de modo a tornar todo um objeto, sua API se torna mais consistente e fácil de usar para os desenvolvedores.

Por exemplo: digamos que um desenvolvedor grave código genérico para usar sua API para mostrar páginas de lista e detalhes. Ele não deseja criar uma exceção porque às vezes é uma matriz e às vezes é um objeto com uma propriedade de lista.

No total, essa resposta não tem nada a ver com princípios sobre descanso, ódio e outros protocolos, mas apenas é real sobre os dados que você precisa enviar ao cliente. Se você decidir seguir, por exemplo, ódios, então, obviamente, atenha-se aos seus padrões (que também são objetos).


3
+1 por "ser real sobre os dados" (e ao mesmo tempo em que reconhece que existe uma definição mais técnica e mais precisa para o REST).
Threed 24/05

9

Ambos

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

são Json válidos. Eu não acho que você deva adicionar "lista" se não for necessário, pode até ser confuso porque o que segue é uma matriz, em vez de uma lista.

Melhor prática REST? A API deve dar resposta adequada ao que quer que esteja definido no cabeçalho Accept e também boa documentação.


7

O motivo pelo qual sua resposta é compatível com JSON é que JSON é um padrão padrão; qualquer idioma com um analisador JSON pode analisá-lo trivialmente e, se você estiver usando JavaScript, nem precisará de um analisador, pois o JavaScript o entende de forma nativa.

Em outras palavras, torne-o compatível com JSON e você não precisará escrever seu próprio analisador. Além disso, não haverá surpresas quando o próximo desenvolvedor escrever um software que consome o serviço.

O REST não tem nada a ver com seu esquema JSON. Qualquer esquema é aceitável, da perspectiva REST.


9
Isso responde a pergunta? Eu li como "Devo usar uma matriz json ou um objeto json como raiz?". Ambos podem ser analisados ​​com analisadores json, para que sua resposta não os ajude a decidir.
CodesInChaos

Então isso não importa. Eu atualizei minha resposta.
Robert Harvey

Se estamos falando de REST, o esquema não importa, desde que seja capaz de fornecer os controles hipermídia para a descoberta e manipulação de outros recursos com base apenas na resposta e em nenhuma outra informação fora de banda ... nenhum dos formatos mencionados pelo OP parece funcionar.
toniedzwiedz

...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.Bem, sim e não. JSON é um subconjunto de JavaScript, mas chamar, em evalvez de usar um analisador, imediatamente torna você vulnerável a "JSON" que contém código malicioso, e a análise provavelmente é muito mais eficiente do que evalqualquer outra maneira.
Doval

5

Um dicionário com uma única "lista" de chaves sem sentido e um valor de matriz é inútil - retorne uma matriz.

Se o mesmo serviço puder retornar livros, CDs ou DVDs, você poderá retornar um dicionário com uma chave "livros" e um valor de matriz. Pode haver outros "DVDs" importantes com uma variedade de DVDs. Por exemplo, se um cliente pode consultar uma lista de todas as suas compras.

Se você tiver certeza de que a resposta será interpretada apenas como uma lista de livros (se a solicitação disser "me dê uma lista de livros"), apenas uma matriz estará correta.


5

A segunda opção também é o método preferido por razões de segurança. Navegadores mais antigos têm uma vulnerabilidade de segurança que permite que outro código javascript na página da Web roube seus dados se eles forem retornados como uma matriz JSON. Portanto, historicamente, a melhor prática era não retornar matrizes JSON. De fato, havia algumas estruturas cuja função "json-ify" escolhe a opção 2 por padrão quando você passa em uma matriz.

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

ambos são json e aderem ao REST. Eu tornaria a resposta mais descritiva, no seu caso, altere a lista para livros. Ou algo parecido com isto :

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

}}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.