Formato de resposta da JSON API padrão?

Existem normas ou práticas recomendadas para estruturar respostas JSON de uma API? Obviamente, todos os dados do aplicativo são diferentes, de modo que eu não me preocupo com isso, mas sim com o “boilerplate de respostas”, se você quiser. Um exemplo do que quero dizer:

Pedido de sucesso:

{ "success": true, "payload": { /* Application-specific data would go here. */ } } 

Pedido falhado:

 { "success": false, "payload": { /* Application-specific data would go here. */ }, "error": { "code": 123, "message": "An error occurred!" } } 

    Sim, existem alguns padrões (embora algumas liberdades na definição de padrão) que emergiram:

    1. API JSON – A API JSON abrange também a criação e atualização de resources, não apenas respostas.
    2. JSend – Simples e provavelmente o que você já está fazendo.
    3. Protocolo OData JSON – Muito complicado.
    4. HAL – Como o OData, mas com o objective de ser HATEOAS .

    Também há formatos de descrição da API JSON:

    • Swagger
      • Esquema JSON (usado pelo swagger mas você poderia usá-lo sozinho)
    • WADL em JSON
    • RAML
    • HAL porque HATEOAS, em teoria, é auto-descritivo.

    Guia do Google JSON

    data retorno da resposta de sucesso

     { "data": { "id": 1001, "name": "Wing" } } 

    Erro de retorno da resposta de error

     { "error": { "code": 404, "message": "ID not found" } } 

    e se seu cliente for JS, você pode usar if ("error" in response) {} para verificar se há erro.

    Eu acho que um padrão não realmente emergiu (e talvez nunca). Mas independentemente disso, aqui está minha opinião:

    Pedido de sucesso:

     { "status": "success", "data": { /* Application-specific data would go here. */ }, "message": null /* Or optional success message */ } 

    Pedido falhado:

     { "status": "error", "data": null, /* or optional error payload */ "message": "Error xyz has occurred" } 

    Vantagem: os mesmos elementos de nível superior em casos de sucesso e erro

    Desvantagem: Nenhum código de erro, mas se você quiser, pode alterar o status para ser um código (sucesso ou falha), ou pode adicionar outro item de nível superior chamado “código”.

    Supondo que você pergunta é sobre design de webservices REST e mais precisamente sobre sucesso / erro.

    Eu acho que existem 3 tipos diferentes de design.

    1. Use somente o código de status HTTP para indicar se houve um erro e tente se limitar aos padrões (normalmente, isso deve ser suficiente).

      • Prós: É um padrão independente da sua API.
      • Contras: Menos informações sobre o que realmente aconteceu.
    2. Use HTTP Status + json body (mesmo que seja um erro). Defina uma estrutura uniforme para erros (ex: código, mensagem, razão, tipo, etc) e use-a para erros, se for um sucesso, então retorne a resposta json esperada.

      • Prós: Ainda é padrão quando você usa os códigos de status HTTP existentes e retorna um json descrevendo o erro (você fornece mais informações sobre o que aconteceu).
      • Contras: O json de saída irá variar dependendo se for um erro ou sucesso.
    3. Esqueça o status http (ex: sempre status 200), sempre use json e adicione na raiz da resposta uma resposta booleanaValid e um object de erro (código, mensagem, etc) que será preenchido se for um erro caso contrário os outros campos (sucesso) são preenchidos.

      • Prós: o cliente lida apenas com o corpo da resposta que é uma cadeia json e ignora o status (?).

      • Contras: O menos padrão.

    Cabe a você escolher 🙂

    Dependendo da API eu escolheria 2 ou 3 (prefiro 2 para json rest apis). Outra coisa que experimentei na criação de REST Api é a importância da documentação para cada recurso (url): os parâmetros, o corpo, a resposta, os headers etc. + exemplos.

    Eu também recomendo que você use jersey (implementação de jax-rs) + genson (biblioteca de binding de dados java / json). Você só tem que soltar o genson + jersey no seu classpath e o json é automaticamente suportado.

    EDITAR:

    • A solução 2 é a mais difícil de implementar, mas a vantagem é que você pode lidar com exceções e não apenas com erros comerciais, o esforço inicial é mais importante, mas você ganha a longo prazo.

    • A solução 3 é fácil de implementar tanto no lado do servidor quanto no cliente, mas não é tão agradável, pois você terá que encapsular os objects que deseja retornar em um object de resposta contendo também o erro responseValid +.

    Eu não serei tão arrogante para afirmar que este é um padrão, então vou usar o formulário “eu prefiro”.

    Eu prefiro uma resposta sucinta (ao solicitar uma lista de / articles eu quero um array JSON de artigos).

    Nos meus projetos eu uso HTTP para relatório de status, um 200 retorna apenas a carga útil.

    400 retorna uma mensagem do que estava errado com o pedido:

     {"message" : "Missing parameter: 'param'"} 

    Retorna 404 se o modelo / controler / URI não existir

    Se houve erro com o processamento do meu lado, retornarei 501 com uma mensagem:

     {"message" : "Could not connect to data store."} 

    Pelo que vi, algumas estruturas REST-ish tendem a ser ao longo destas linhas.

    Fundamentação :

    O JSON deve ser um formato de carga útil , não é um protocolo de session. Toda a idéia de cargas de trabalho verbais vem do mundo XML / SOAP e de várias escolhas equivocadas que criaram esses designs inchados. Depois que percebemos que tudo isso era uma enorme dor de cabeça, o objective do REST / JSON era beijar e aderir ao HTTP. Eu não acho que há algo remotamente padrão no JSend e especialmente não no mais detalhado entre eles. XHR irá reagir à resposta HTTP, se você usar o jQuery para o seu AJAX (como a maioria faz) você pode usar callbacks try / catch and done() / fail() para capturar erros. Não consigo ver como o encapsulamento de relatórios de status no JSON é mais útil do que isso.

    A seguir está o formato json que o instagram está usando

     { "meta": { "error_type": "OAuthException", "code": 400, "error_message": "..." } "data": { ... }, "pagination": { "next_url": "...", "next_max_id": "13872296" } } 

    Por que vale a pena fazer isso de forma diferente. Uma chamada bem-sucedida tem apenas os objects JSON. Não preciso de um object JSON de nível superior que contenha um campo de sucesso indicando true e um campo de carga útil que tenha o object JSON. Acabei de retornar o object JSON apropriado com um 200 ou o que for apropriado no intervalo 200 para o status HTTP no header.

    No entanto, se houver um erro (algo na família 400), retornarei um object de erro JSON bem formado. Por exemplo, se o cliente estiver colocando um usuário no POST com um endereço de e-mail e um número de telefone e um deles estiver malformado (ou seja, não puder inseri-lo no database subjacente), retornarei algo assim:

     { "description" : "Validation Failed" "errors" : [ { "field" : "phoneNumber", "message" : "Invalid phone number." } ], } 

    Os bits importantes aqui são que a propriedade “field” deve corresponder exatamente ao campo JSON que não pôde ser validado. Isso permite que os clientes saibam exatamente o que deu errado com sua solicitação. Além disso, “message” está na localidade da solicitação. Se o “emailAddress” e “phoneNumber” forem inválidos, a matriz “errors” conterá inputs para ambos. Um corpo de respostas JSON 409 (Conflito) pode ter esta aparência:

     { "description" : "Already Exists" "errors" : [ { "field" : "phoneNumber", "message" : "Phone number already exists for another user." } ], } 

    Com o código de status HTTP e esse JSON, o cliente tem tudo o que precisa para responder aos erros de maneira determinística e não cria um novo padrão de erro que tente completar os códigos de status HTTP. Observe que isso ocorre apenas no intervalo de 400 erros. Para qualquer coisa na faixa dos 200, posso simplesmente retornar o que for apropriado. Para mim, muitas vezes é um object JSON parecido com HAL, mas isso não importa realmente aqui.

    A única coisa que pensei em adicionar foi um código de erro numérico nas inputs de matriz “errors” ou na raiz do próprio object JSON. Mas até agora não precisamos disso.

    O RFC 7807: Detalhes do Problema para APIs HTTP é, no momento, a coisa mais próxima que temos de um padrão oficial.

    O ponto do JSON é que é completamente dynamic e flexível. Dobre-o para qualquer whim que você quiser, porque é apenas um conjunto de matrizes e objects JavaScript serializados, enraizados em um único nó.

    Qual é o tipo do rootnode depende de você, o que ele contém é você, se você enviar metadados junto com a resposta é com você, se você definir o tipo mime para application/json ou deixá-lo como text/plain é com você (contanto que você saiba como lidar com os casos de borda).

    Construa um esquema leve que você goste.
    Pessoalmente, descobri que rastreamento de análise e serviço de mp3 / ogg e serviço de galeria de imagens e mensagens de texto e pacotes de rede para jogos on-line, além de postagens de blog e comentários de blog, têm requisitos muito diferentes em termos do que é enviado e o que é recebido e como devem ser consumidos.

    Então, a última coisa que eu quero, ao fazer tudo isso, é tentar fazer com que cada um esteja em conformidade com o mesmo padrão clichê, que é baseado em XML2.0 ou algo assim.

    Dito isto, há muito a ser dito sobre o uso de esquemas que fazem sentido para você e são bem pensados.
    Basta ler algumas respostas da API, observar o que você gosta, criticar o que você não gosta, escrever essas críticas e entender por que elas o atrapalham de maneira errada e depois pensar em como aplicar o que você aprendeu ao que você precisa.

    Não há acordo sobre os demais formatos de respostas api de grandes gigantes do software – Google, Facebook, Twitter, Amazon e outros, embora muitos links tenham sido fornecidos nas respostas acima, onde algumas pessoas tentaram padronizar o formato de resposta.

    Como as necessidades da API podem diferir, é muito difícil include todos e concordar com algum formato. Se você tem milhões de usuários usando sua API, por que você mudaria seu formato de resposta?

    Segue minha opinião sobre o formato de resposta inspirado no Google, Twitter, Amazon e alguns posts na internet:

    https://github.com/adnan-kamili/rest-api-response-format

    Arquivo Swagger:

    https://github.com/adnan-kamili/swagger-sample-template

    O JSON-RPC 2.0 define um formato padrão de solicitação e resposta e é uma lufada de ar fresco depois de trabalhar com APIs REST.

    Melhor resposta para web apis que pode ser facilmente entendido pelos desenvolvedores de dispositivos móveis.

    Isto é para a resposta “sucesso”

     { "ReturnCode":"1", "ReturnMsg":"Successfull Transaction", "ReturnValue":"", "Data":{ "EmployeeName":"Admin", "EmployeeID":1 } } 

    Isso é para a resposta “Erro”

     { "ReturnCode": "4", "ReturnMsg": "Invalid Username and Password", "ReturnValue": "", "Data": {} }