Introdução Completa à Especificação JSON:API

Rebecca Kovács

Rebecca Kovács

19 maio 2025

Introdução Completa à Especificação JSON:API

REST (Representational State Transfer) fornece um estilo arquitetural fundamental para a construção de serviços web. No entanto, deixa muitos aspectos da formatação de requisições e respostas indefinidos. Essa ambiguidade pode levar a inconsistências, aumento da sobrecarga de desenvolvimento e uma curva de aprendizado mais íngreme para os consumidores de API. Surge o JSON:API, uma especificação que fornece uma abordagem padronizada e baseada em convenções para a construção de APIs em JSON.

Este guia abrangente oferece um mergulho profundo na especificação JSON:API, explorando seus conceitos centrais, estrutura e recursos poderosos. Dissecaremos seus mecanismos para buscar, criar, atualizar e excluir recursos, gerenciar relacionamentos, lidar com erros e otimizar a transferência de dados, equipando você com o conhecimento para projetar e consumir APIs robustas e eficientes.

💡
Quer uma ótima ferramenta de Teste de API que gera documentação de API bonita?

Quer uma plataforma integrada e completa para sua Equipe de Desenvolvedores trabalhar em conjunto com produtividade máxima?

Apidog entrega todas as suas demandas e substitui o Postman a um preço muito mais acessível!
button

Por que JSON:API? Explicado:

Antes de nos aprofundarmos nas complexidades técnicas, é crucial entender os problemas que o JSON:API busca resolver. Sem uma convenção compartilhada, desenvolvedores de API frequentemente gastam um tempo considerável debatendo:

O JSON:API aborda essas questões definindo um formato claro e consistente para requisições e respostas. Essa padronização oferece vários benefícios chave:

Conceitos Centrais: Os Blocos de Construção de um Documento JSON:API

Em sua essência, o JSON:API gira em torno do conceito de recursos. Um recurso é um registro individual de um tipo particular, como um "artigo", um "usuário" ou um "produto". Cada documento JSON:API, seja uma requisição ou uma resposta, adere a uma estrutura específica.

A Estrutura do Documento: Membros de Nível Superior

Um documento JSON:API é um objeto JSON que deve conter pelo menos um dos seguintes membros de nível superior:

Além disso, um documento pode conter estes membros de nível superior:

Objetos de Recurso: Representando Seus Dados

Um objeto de recurso é a pedra angular do JSON:API e deve conter:

Um objeto de recurso pode também conter:

Exemplo de um Objeto de Recurso:JSON

{
  "type": "articles",
  "id": "1",
  "attributes": {
    "title": "JSON:API Revelado",
    "body": "Um mergulho profundo na especificação...",
    "created_at": "2025-05-15T10:00:00Z",
    "updated_at": "2025-05-16T14:30:00Z"
  },
  "relationships": {
    "author": {
      "links": {
        "self": "/articles/1/relationships/author",
        "related": "/articles/1/author"
      },
      "data": { "type": "users", "id": "42" }
    },
    "comments": {
      "links": {
        "self": "/articles/1/relationships/comments",
        "related": "/articles/1/comments"
      },
      "data": [
        { "type": "comments", "id": "5" },
        { "type": "comments", "id": "12" }
      ]
    }
  },
  "links": {
    "self": "/articles/1"
  }
}

Objetos Identificadores de Recurso

Objetos identificadores de recurso são representações mínimas de um recurso, contendo apenas type e id. Eles são usados dentro de objetos de relacionamento para vincular a outros recursos sem incorporar o objeto de recurso completo.

Exemplo de um Objeto Identificador de Recurso:JSON

{ "type": "users", "id": "42" }

Objetos links fornecem URLs para navegar na API. Membros de link comuns incluem:

Um link pode ser representado como:

Exemplo de um Objeto Links (dentro de um relacionamento):JSON

"links": {
  "self": "http://example.com/articles/1/relationships/author",
  "related": "http://example.com/articles/1/author"
}

Objetos Meta

Objetos meta permitem a inclusão de meta-informações não padrão. Isso pode ser pares arbitrários de chave-valor. Por exemplo, um objeto meta poderia incluir informações de direitos autorais ou timestamps relacionados aos dados.

Exemplo de um Objeto Meta:JSON

"meta": {
  "copyright": "Copyright 2025 Example Corp.",
  "authors": ["John Doe"]
}

Negociação de Conteúdo: Falando a Língua Certa

O JSON:API define seu próprio tipo de mídia: application/vnd.api+json.

Os servidores podem suportar outros tipos de mídia juntamente com application/vnd.api+json através da negociação de conteúdo padrão.

Busca de Dados: Recuperando Recursos e Coleções

O JSON:API fornece mecanismos robustos para que os clientes recuperem dados precisamente conforme necessário.

Buscando Recursos Individuais

Para buscar um único recurso, um cliente envia uma requisição GET para um endpoint representando esse recurso.

Requisição:

GET /articles/1

Accept: application/vnd.api+json

Resposta Bem-Sucedida (200 OK):JSON

{
  "links": {
    "self": "/articles/1"
  },
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API é Demais!"
    }
    // ... outros atributos e relacionamentos
  }
}

Se o recurso não existir, o servidor deve retornar um 404 Not Found. Se um link de recurso relacionado um-para-um for buscado e o relacionamento estiver vazio, os dados primários serão null.

Buscando Coleções de Recursos

Para buscar uma coleção de recursos, um cliente envia uma requisição GET para um endpoint representando essa coleção.

Requisição:

GET /articles

Accept: application/vnd.api+json

Resposta Bem-Sucedida (200 OK):JSON

{
  "links": {
    "self": "/articles",
    "next": "/articles?page[offset]=10",
    "last": "/articles?page[offset]=50"
  },
  "data": [
    {
      "type": "articles",
      "id": "1",
      "attributes": { "title": "Artigo 1" }
      // ...
    },
    {
      "type": "articles",
      "id": "2",
      "attributes": { "title": "Artigo 2" }
      // ...
    }
    // ... mais artigos
  ]
}

Se a coleção estiver vazia, o membro data será um array vazio [].

Relacionamentos: Conectando Recursos

Relacionamentos são uma parte fundamental da maioria dos modelos de dados. O JSON:API fornece uma maneira clara de defini-los e interagir com eles.

Representando Relacionamentos

Relacionamentos são definidos dentro do objeto relationships de um recurso. Cada entrada no objeto relationships representa um relacionamento distinto (por exemplo, "author", "comments").

Um objeto relationship deve conter pelo menos um de:

Exemplo de relacionamentos "author" (um-para-um) e "comments" (um-para-muitos):JSON

"relationships": {
  "author": {
    "links": {
      "self": "/articles/1/relationships/author",
      "related": "/articles/1/author"
    },
    "data": { "type": "users", "id": "42" }
  },
  "comments": {
    "links": {
      "self": "/articles/1/relationships/comments",
      "related": "/articles/1/comments"
    },
    "data": [
      { "type": "comments", "id": "5" },
      { "type": "comments", "id": "12" }
    ]
  }
}

Buscando Relacionamentos

Os clientes podem buscar informações sobre um relacionamento em si ou sobre os recursos relacionados usando os links fornecidos.

Buscando a Ligação do Relacionamento (link self):

GET /articles/1/relationships/comments

Accept: application/vnd.api+json

Isso retorna uma coleção de objetos identificadores de recurso para os comentários relacionados ao artigo "1".

Buscando Recursos Relacionados (link related):

GET /articles/1/comments

Accept: application/vnd.api+json

Isso retorna uma coleção de objetos de recurso de comentário completos relacionados ao artigo "1".

Otimizando a Recuperação de Dados

O JSON:API oferece vários recursos para otimizar como os dados são recuperados, minimizando a largura de banda e melhorando o desempenho do lado do cliente.

Documentos Compostos: Reduzindo Requisições HTTP com include

Para evitar múltiplas viagens de ida e volta ao servidor para buscar recursos relacionados, o JSON:API permite que os clientes solicitem que recursos relacionados sejam incluídos na resposta primária usando o parâmetro de query include. O servidor então carregará esses recursos lateralmente ("sideload") no array included de nível superior.

Requisição para buscar um artigo e incluir seu autor e comentários:

GET /articles/1?include=author,comments

Accept: application/vnd.api+json

Resposta (200 OK):JSON

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": { "title": "..." },
    "relationships": {
      "author": {
        "data": { "type": "users", "id": "42" }
      },
      "comments": {
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    }
  },
  "included": [
    {
      "type": "users",
      "id": "42",
      "attributes": { "name": "John Doe" }
    },
    {
      "type": "comments",
      "id": "5",
      "attributes": { "body": "Ótimo artigo!" }
    },
    {
      "type": "comments",
      "id": "12",
      "attributes": { "body": "Muito informativo." }
    }
  ]
}

Sparse Fieldsets (Conjuntos Esparsos de Campos): Buscando Apenas os Campos Necessários

Os clientes podem solicitar que apenas campos específicos (atributos e relacionamentos) sejam retornados para recursos de um determinado tipo usando o parâmetro de query fields[TYPE]. Isso reduz o tamanho do payload.

Requisição para buscar artigos, mas apenas seus títulos e o relacionamento com o autor:

GET /articles?fields[articles]=title,author

Accept: application/vnd.api+json

Resposta (200 OK):JSON

{
  "data": [
    {
      "type": "articles",
      "id": "1",
      "attributes": {
        "title": "Artigo 1"
      },
      "relationships": {
        "author": {
          "data": { "type": "users", "id": "42" }
        }
      }
    }
    // ... outros artigos com apenas título e autor
  ]
}

Ordenação (Sorting)

Os clientes podem solicitar que os dados primários sejam ordenados usando o parâmetro de query sort.

Requisição para buscar artigos ordenados por data de criação (descendente) e depois por título (ascendente):

GET /articles?sort=-created_at,title

Accept: application/vnd.api+json

Paginação

O JSON:API suporta várias estratégias de paginação. A especificação define como os links de paginação (first, prev, next, last) devem aparecer no objeto links de nível superior. A estratégia de paginação real (por exemplo, baseada em página, baseada em offset, baseada em cursor) é determinada pelo servidor usando parâmetros de query como page[number], page[size], page[offset], page[limit] ou page[cursor].

Exemplo de links de paginação baseada em página:JSON

"links": {
  "self": "/articles?page[number]=2&page[size]=10",
  "first": "/articles?page[number]=1&page[size]=10",
  "prev": "/articles?page[number]=1&page[size]=10",
  "next": "/articles?page[number]=3&page[size]=10",
  "last": "/articles?page[number]=5&page[size]=10"
}

Os clientes devem usar esses links fornecidos em vez de construir suas próprias URLs de paginação.

Filtragem (Filtering)

A especificação reserva o parâmetro de query filter para filtrar dados. No entanto, não impõe uma estratégia de filtragem específica. Os servidores podem implementar qualquer estratégia, como filter[attribute]=value ou filtragem baseada em expressões mais complexas.

Exemplo (recomendado pelo JSON:API, mas não obrigatório):

GET /comments?filter[post]=1 (Obter comentários para o post com ID 1)

GET /comments?filter[post]=1,2&filter[author]=12 (Obter comentários para os posts 1 ou 2, pelo autor 12)

Os clientes devem consultar a documentação da API para entender suas capacidades de filtragem específicas.

Modificando Dados: Criando, Atualizando e Excluindo Recursos

O JSON:API define protocolos claros para operações de manipulação de dados.

Criando Recursos

Para criar um recurso, um cliente envia uma requisição POST para uma URL representando uma coleção de recursos. O corpo da requisição deve conter um único objeto de recurso com type e, opcionalmente, attributes e relationships. O cliente não deve fornecer um id para o novo recurso (a menos que IDs gerados pelo cliente sejam suportados e habilitados).

Requisição:

POST /articles

Accept: application/vnd.api+json

Content-Type: application/vnd.api+jsonJSON

{
  "data": {
    "type": "articles",
    "attributes": {
      "title": "Título do Novo Artigo",
      "body": "Conteúdo do novo artigo."
    },
    "relationships": {
      "author": {
        "data": { "type": "users", "id": "42" }
      }
    }
  }
}

Respostas Bem-Sucedidas:

Se uma tentativa for feita para criar um recurso com um ID gerado pelo cliente que já existe, e o servidor não suportar atualização via POST, ele deve retornar 409 Conflict.

Atualizando Recursos

Recursos são atualizados usando o método HTTP PATCH. A requisição deve incluir o id do recurso a ser atualizado. O corpo da requisição contém um objeto de recurso com type, id e os attributes e/ou relationships a serem atualizados.

Requisição para atualizar o título de um artigo e um de seus relacionamentos:

PATCH /articles/1

Accept: application/vnd.api+json

Content-Type: application/vnd.api+jsonJSON

{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "Título do Artigo Atualizado"
    },
    "relationships": {
      "tags": {
        "data": [
          { "type": "tags", "id": "3" },
          { "type": "tags", "id": "4" }
        ]
      }
    }
  }
}

Pontos chave para atualizações:

Respostas Bem-Sucedidas:

Se o recurso a ser atualizado não existir, o servidor deve retornar 404 Not Found.

Atualizando Relacionamentos Diretamente

O JSON:API fornece maneiras específicas de gerenciar relacionamentos sem afetar os atributos do recurso primário.

{
  "data": { "type": "users", "id": "24" } // Atribuir novo autor ou null para limpar
}
{
  "data": [
    { "type": "comments", "id": "101" },
    { "type": "comments", "id": "102" }
  ]
}
{
  "data": [
    { "type": "comments", "id": "103" }
  ]
}
{
  "data": [
    { "type": "comments", "id": "5" }
  ]
}

Atualizações de relacionamento bem-sucedidas geralmente retornam 200 OK ou 204 No Content.

Excluindo Recursos

Para excluir um recurso, um cliente envia uma requisição DELETE para o endpoint do recurso.

Requisição:

DELETE /articles/1

Accept: application/vnd.api+json

Resposta Bem-Sucedida:

Se o recurso não existir, o servidor deve retornar 404 Not Found. A especificação não dita como recursos ou relacionamentos relacionados devem ser tratados após a exclusão (por exemplo, exclusões em cascata); isso é um detalhe de implementação.

Tratamento de Erros

Quando um erro ocorre, os servidores devem usar códigos de status HTTP apropriados (4xx para erros do cliente, 5xx para erros do servidor). O corpo da resposta deve conter um documento de erro JSON:API.

Um documento de erro inclui um membro errors de nível superior, que é um array de objetos de erro. Cada objeto de erro pode conter:

Exemplo de Resposta de Erro (422 Unprocessable Entity):JSON

{
  "errors": [
    {
      "status": "422",
      "source": { "pointer": "/data/attributes/email" },
      "title": "Atributo Inválido",
      "detail": "O endereço de e-mail não é válido."
    },
    {
      "status": "422",
      "source": { "pointer": "/data/relationships/author" },
      "title": "Valor de Relacionamento Inválido",
      "detail": "Autor com ID '999' não existe."
    }
  ]
}

Considerações do Lado do Servidor e Melhores Práticas

Embora a especificação central seja abrangente, o JSON:API também fornece recomendações para aspectos como design de URL e nomenclatura de membros.

Design de URL

Nomenclatura de Membros

Estendendo a Especificação: Extensões e Perfis

O JSON:API é projetado para ser extensível para atender a necessidades em evolução e casos de uso específicos.

Extensões

Extensões podem introduzir novas funcionalidades não cobertas pela especificação base. Um exemplo é a extensão "Atomic Operations", que permite que múltiplas operações (criar, atualizar, excluir) sejam realizadas em uma única requisição atômica. Tanto o cliente quanto o servidor devem entender uma extensão para que ela seja usada. Se um servidor receber uma requisição com uma extensão não suportada, ele deve responder com um erro apropriado.

Perfis

Perfis definem um conjunto de convenções sobre a especificação base para um caso de uso particular (por exemplo, uma maneira específica de lidar com timestamps ou um conjunto comum de atributos meta). Ao contrário das extensões, os perfis podem ser seguramente ignorados se não forem compreendidos por uma das partes. Eles são destinados a promover a interoperabilidade para padrões comuns sem exigir mudanças na especificação central ou obrigar suporte universal.

Os servidores podem anunciar extensões e perfis suportados no objeto jsonapi de nível superior. Isso permite que os clientes descubram essas capacidades e adaptem suas requisições de acordo.

O Futuro do JSON:API

O JSON:API continua a evoluir, impulsionado pela contribuição da comunidade e pela necessidade de abordar desafios emergentes de design de API. Seu foco em convenção sobre configuração, eficiência e experiência do desenvolvedor solidificou seu lugar como um padrão líder para a construção de APIs modernas. Ao adotar o JSON:API, as equipes de desenvolvimento podem reduzir significativamente a ambiguidade, aprimorar a interoperabilidade e acelerar o ritmo do desenvolvimento e consumo de API.

Esta exploração detalhada cobre a vasta maioria da especificação JSON:API. Ao entender e implementar esses princípios, os desenvolvedores podem criar APIs que não são apenas funcionais, mas também limpas, consistentes e agradáveis de trabalhar, promovendo, em última análise, um ecossistema de API mais produtivo e colaborativo.

Explore more

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs