design da API RESTful. O que devo retornar se não houver linhas?

50

Atualmente, estou codificando uma API para uma rede social com o Slim Framework. Minha pergunta é: Quais são as melhores práticas quando não há linhas para retornar na estrutura do json?

Digamos que essa chamada / v1 / get / movies retorne 2 linhas dos nomes dos filmes da tabela:

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

Mas eu chamo / v1 / get / books e não há linhas nessa tabela. Devo devolver uma estrutura vazia?

[
]

... ou seria melhor uma mensagem e um código de erro?

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

Qual é uma prática melhor? (a API será usada em aplicativos iOS e Android) Obrigado!

    
por Andres SK 29.05.2013 / 08:09
fonte

14 respostas

45

Normalmente, eu retornaria o número de registros no resultado como metadados. Não tenho certeza se isso é uma prática REST normal, mas não é muito mais dados, e é muito preciso. Geralmente há paginação para muitos serviços, é impraticável retornar um conjunto de resultados enorme de uma só vez. Pessoalmente estou irritado quando há paginação para pequenos conjuntos de resultados. Se estiver vazio, retorne number_of_records : 0 e livros como lista vazia / array books : [] .

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

EDIT (alguns anos depois): Resposta de Martin Wickman é muito melhor, aqui é "curto" de explicação porque.

Ao lidar com a paginação, tenha sempre em mente a possibilidade de conteúdos ou pedidos de alteração. Como, primeiro pedido vem, 24 resultados, você retorna primeiro 10. Depois disso, "novo livro" é inserido e agora você tem 25 resultados, mas com o pedido original, seria ordenado em 10º lugar. Quando o primeiro usuário solicita a segunda página, ele não recebe "novo livro". Existem maneiras de lidar com tais problemas, como fornecer "id de solicitação", que deve ser enviado com as seguintes chamadas de API, retornando a próxima página do conjunto de resultados "antigo", que deve ser armazenado de alguma forma e vinculado a "id de solicitação". Alternativa é adicionar campo como "lista de resultados alterada desde a primeira solicitação".

Geralmente, se você puder, tente colocar um esforço extra e evitar a paginação. A paginação é um estado adicional que pode sofrer mutação e rastrear essas alterações é propenso a erros, ainda mais porque tanto o servidor quanto o cliente precisam lidar com isso.

Se você tiver muitos dados para processar de uma só vez , considere retornar "id list" com todos os resultados e detalhes de algum trecho dessa lista e fornecer chamadas de API multi_get / get_by_id_list para recursos. / p>     

por 29.05.2013 / 08:52
fonte
105

Seu exemplo está quebrado. Você não deve ter objetos json com chaves duplicadas. O que você está procurando é uma matriz com objetos de filme, assim:

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

Essa abordagem também responde à sua pergunta. Você deve retornar uma matriz vazia quando a consulta não corresponder:

[]

Por outro lado, se você tentar obter um recurso de filme específico com GET api/movie/34 e esse filme não existir, retorne 404 com uma mensagem de erro adequada (codificada json) no corpo

    
por 29.05.2013 / 10:27
fonte
15

Se este for JSON, você deve considerar retornar um Array de objetos. Isso tem muitas vantagens, inclusive quando você não tem registros, é uma matriz vazia.

Então, quando você tiver registros, você retornará:

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

E quando você não tem registros, você retornaria:

    [

    ]
    
por 29.05.2013 / 09:10
fonte
14

Se você executar a operação com sucesso, mas não tiver nada para retornar, como o mapa vazio {} ou a matriz vazia [] preferiria responder com 204 códigos de resposta, aqui está um excerto de Definições do código de status do HTTP especificações:

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.

Essencialmente, recomendo usar 204 em aplicativos RESTful sobre HTTP quando não houver nada para retornar.

    
por 29.05.2013 / 14:01
fonte
10

Houve uma quantidade razoável de trabalho na criação de um formato JSON API padronizado .

Seguir os princípios nessa especificação significa que todos os recursos retornados devem ser efetivamente "coleções" (mesmo quando apenas um único recurso é incluído). A seguir, isso significaria que sua chamada para /v1/get/movies retornaria:

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

Sua chamada para /v1/get/books (que retorna zero recursos) retornaria:

{
    "books": []
}
    
por 29.05.2013 / 19:44
fonte
5

Para o seu exemplo específico, recomendo que o / v1 / get / books retorne o HTTP 200 com um array vazio.

Se eu estou lendo sua postagem corretamente, sua API pretende coletar livros. Metaforicamente falando, você tem uma estante de livros, um DVD para filmes e possivelmente outros recipientes que você não mencionou aqui. Porque você pretende coletar livros, / v1 / get / books é sua estante. Isso significa que há um recurso válido lá - uma lista de livros - que está vazia no seu exemplo específico.

O motivo pelo qual não sugiro o retorno do HTTP 404 neste caso é que a estante de livros ainda está lá. Não há livros sobre isso no momento, mas ainda é uma estante de livros. Se não fosse uma estante de livros, se a API não pretendesse coletar livros, por exemplo, o então HTTP 404 seria apropriado. Mas como há um recurso lá, você não deve sinalizar que não existe um, o que o HTTP 404 faz. Portanto, eu argumento que 200 com uma matriz vazia (significando a coleção) é mais apropriado.

O motivo pelo qual eu não sugiro o retorno do HTTP 204 é que isso sugeriria que "No Content" é o estado de coisas comum: executar essa ação nesse recurso normalmente não retornaria nada. É por isso que normalmente é usado como resposta a solicitações DELETE, por exemplo: a natureza da exclusão geralmente significa que não resta nada para retornar. O caso é semelhante quando usado para responder a solicitações com a família de cabeçalhos If-Modified: você só queria conteúdo se o recurso tivesse mudado, mas não, então eu não vou te dar nenhum conteúdo.

Mas eu argumento que para obter uma coleção vazia, mas válida, o HTTP 204 não faz sentido. Se houvesse itens na coleção, a representação apropriada seria uma matriz desses dados. Portanto, quando não há dados (mas a coleção é válida), a representação apropriada é uma matriz vazia.

    
por 06.02.2014 / 20:14
fonte
5

Você realmente deve fazer apenas uma das duas coisas

Retorna um código de status 200 (OK) e uma matriz vazia no corpo.

Ou Retornar um código de status 204 (NO CONTENT) e nenhum corpo de resposta.

Para mim, a opção 2 parece mais tecnicamente correta e está alinhada com os princípios REST e HTTP.

No entanto, a opção 1 parece mais eficiente para o cliente - porque o cliente não precisa de lógica extra para diferenciar entre dois códigos de status (de sucesso). Como ele sabe que sempre receberá um array, ele simplesmente precisa verificar se ele tem nenhum, um ou muitos itens e processá-lo adequadamente

    
por 29.09.2014 / 18:48
fonte
3

Eu vi os dois casos em ambientes de produção. Qual deles você escolhe depende de quem usará a API. Se eles querem saber por que a lista está vazia ou para ter certeza de que a lista está realmente vazia e nenhum erro ocorreu durante a recuperação, você deve anexar um objeto "errors". Se eles não se importarem, retornem uma lista vazia. Eu iria com a segunda abordagem, uma vez que abrange mais necessidades do que o primeiro.

    
por 29.05.2013 / 08:49
fonte
3

A primeira coisa a considerar, já que você está criando uma API RESTful, é retornar um código de resposta apropriado. E o código de resposta mais apropriado para comunicar que a solicitação passou normalmente, mas o recurso solicitado não está disponível no momento é o venerável 404.

Se você projetar sua API de modo que ela sempre retorne um código de resposta sensato, talvez você nem precise retornar um corpo quando o recurso não foi encontrado. Dito isto, retornar um corpo, especialmente um humanamente legível, não pode ferir.

Não há "melhor prática" aqui, seus dois exemplos são arbitrários, basta escolher um e ser consistente . Os desenvolvedores odeiam surpresas, se /v1/get/movies retornar {} quando não houver filmes, então esperamos que /v1/get/actors também retorne {} quando não houver atores.

    
por 29.05.2013 / 08:49
fonte
1

Eu não acho que a resposta correta seja a que está marcada.

A resposta fornecida pelo nirth deve ser a melhor, em um verdadeiro cenário REST. A resposta do corpo deve estar vazia e o código de status http: 204; o recurso existe, mas não tem "conteúdo" naquele momento: está vazio.

HTTP_Status_Codes do REST

    
por 04.06.2013 / 11:32
fonte
1

Eu recomendo 200 + array vazio, pois simplifica o manuseio por todos os clientes da API. 200 + array significa "Eu retornei todos os dados que estão lá". Tanto para o código que entrega os dados quanto para o processamento do código, o número de itens seria irrelevante.

Todos os outros códigos de status precisam ser adequadamente documentados e entregues corretamente pelo servidor e processados adequadamente pelo cliente, e todos sabemos como isso é provável.

Houve uma sugestão para retornar status 204 + corpo vazio. Isso significa que você força o todo único cliente a processar o status 204 corretamente. Além disso, você os força a lidar com respostas não-JSON! Espero que todos percebam que só porque um pedido recebeu uma resposta, isso não significa que a resposta veio do servidor quando o http é usado, e apenas uma verificação de que a resposta é o JSON lida com muitos desses casos.

    
por 22.11.2015 / 14:57
fonte
0

Eu gostaria "Depende".

Se zero for um resultado razoável, retorne a lista vazia. Por exemplo, se você quiser obter todos os funcionários chamados "bob", onde "nenhum" é um resultado bastante razoável. Se não for um resultado esperado, retorne um erro. Por exemplo, obtendo uma lista histórica de endereços para uma pessoa que você emprega. Eles devem viver em algum lugar para que nenhum resultado seja provavelmente um erro, não apenas uma condição normal.

Tenho certeza que você pode argumentar com os detalhes do meu exemplo, mas você tem a idéia ...

    
por 06.02.2014 / 13:58
fonte
0
  • Primeiro, ter get em sua URL não é RESTful, GET está implícito no método HTTP.
  • Se você estiver solicitando uma coleção como GET api/movies , retorne um 200 OK com uma matriz vazia [] .
  • Se você estiver solicitando um filme específico como GET api/movies/1 (onde 1 é o id) e ele não existe, retorne um 404 Not Found .

Por quê? Você está solicitando recursos . Quando você está solicitando a coleção, o recurso em si (a coleção) existe. Por isso, um 404 está errado. Mas se você solicitar um filme específico e ele não existir, o recurso solicitado não existirá e você deverá retornar um 404 .

    
por 22.11.2015 / 13:35
fonte
-2

Se você estiver retornando JSON, é melhor sempre retornar a contagem e a mensagem de erro, e talvez um Booleano que indique se há erro ou não, que são os meus três meta valores padrão retornados com cada lista de linhas.

    
por 22.11.2015 / 15:12
fonte