Anúncios incomodam? Ir Sem anúncios Hoje

Esquemas de GraphQL Escreva, Formate e Entenda SDL Sem o Código Repetitivo

Atualizado em

Os esquemas GraphQL são contratos auto-documentados entre servidor e cliente. Este guia orienta você passo a passo sobre a Linguagem de Definição de Esquema (SDL) — tipos, escalares, consultas, mutações, tipos de entrada, enums e interfaces — para que você possa ler e escrever esquemas com confiança.

Esquemas de GraphQL: Escreva, Formate e Entenda o SDL Sem o Boilerplate 1
ANUNCIADO Remover?

Se você já trabalhou com APIs REST e então abriu um esquema de GraphQL pela primeira vez, a sintaxe provavelmente pareceu familiar, mas não totalmente parseável. Isso é normal. A Linguagem de Definição de Esquema (SDL) é concisa, mas carrega muito significado por linha. Este artigo o descompõe para que você possa ler e escrever esquemas sem precisar consultar as documentações a cada cinco minutos.

O que um Esquema de GraphQL É de Fato

Um esquema de GraphQL é o contrato entre seu servidor de API e cada cliente que o utiliza. Ele define exatamente quais dados existem, quais operações estão disponíveis e qual a forma que as respostas assumem. Diferentemente do REST — onde você descobre endpoints por meio de documentação, tentativa e erro — o GraphQL torna o contrato explícito e legível por máquinas.

Todo API de GraphQL começa com um esquema escrito em SDL. O servidor valida todas as consultas contra ele em tempo de execução. Se um cliente pede um campo que não existe no esquema, a solicitação é rejeitada antes que qualquer resolutor seja executado. Esse é o valor central do sistema de tipos do GraphQL: o esquema é a fonte de verdade para a superfície da sua API.

Fundamentos do SDL: Tipos, Consultas e Mutações

Cada arquivo SDL é construído a partir de definições de tipo. Aqui está o esquema mais simples possível:

type Query {
  hello: String
}

Query é o ponto de entrada para operações de leitura. Todo esquema deve ter um. O campo hello retorna um String — um dos cinco tipos escalares integrados.

Os cinco escalares integrados são:

  • String — texto UTF-8
  • Int — inteiro de 32 bits assinado
  • Float — ponto flutuante de precisão dupla
  • Boolean — verdadeiro ou falso
  • ID — um identificador único, serializado como uma string

Esquemas reais definem tipos personalizados de objetos. Aqui está um padrão mais típico:

type User {
  id: ID!
  name: String!
  email: String!
  role: UserRole!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  body: String
  author: User!
  publishedAt: DateTime
}

type Query {
  user(id: ID!): User
  posts: [Post!]!
}

Há muito acontecendo nessas 20 linhas. Vamos desmontá-lo.

Campos Não-Nulos e Listas

O ! após um tipo significa que o campo é não-nulo — ele nunca retornará null. Sem isso, o campo é nulo e o cliente deve lidar com um valor ausente. Essa distinção importa em tempo de execução: se um resolutor de campo não-nulo lançar ou retornar null, o GraphQL propagará o null pela árvore, potencialmente nulando campos pai também.

Listas usam colchetes: [Post] é uma lista nula de posts nulos. [Post!]! é uma lista não-nula de posts não-nulos. Essa é a versão que você geralmente deseja — um campo que sempre retorna um array (possivelmente vazio) e cada elemento dentro dele é sempre um objeto real, não nulo.

As quatro combinações, detalhadas:

  • [Post] — lista nula, itens nulos (raramente úteis)
  • [Post!] — lista nula, itens não-nulos
  • [Post]! — lista não-nula, itens nulos
  • [Post!]! — lista não-nula, itens não-nulos (mais comum)

Mutações: Escrita de Dados

As consultas são somente leitura. As mutações lidam com escritas. O tipo Mutation é estruturado da mesma forma que Query, mas por convenção seus campos têm efeitos colaterais:

type Mutation {
  createPost(input: CreatePostInput!): Post!
  deletePost(id: ID!): Boolean!
}

Perceber CreatePostInput! — é um tipo de entrada, o que leva diretamente ao conceito seguinte.

Tipos de Entrada vs Tipos de Saída

Este é um dos pontos mais comuns de confusão em esquemas de GraphQL. Você não pode reutilizar um tipo de objeto como Post como argumento de uma mutação. O SDL tem dois tipos separados por uma razão:

  • Tipos de objeto (type) — usados em respostas. Podem conter resolutores e lógica complexa de campos.
  • Tipos de entrada (input) — usados em argumentos. Dados simples, sem resolutores. Os campos podem apenas referenciar escalares ou outros tipos de entrada.
input CreatePostInput {
  title: String!
  body: String
  authorId: ID!
}

Essa separação mantém a validação de argumentos limpa e evita problemas de referência circular que surgiriam se os tipos de saída (que podem se referir uns aos outros em grafos complexos) fossem usados diretamente como entradas.

Escalares Personalizados

Os cinco escalares integrados não cobrem tudo. Uma string de data-hora, uma URL, um lote de JSON — esses precisam de escalares personalizados. Você os declara assim:

scalar DateTime
scalar JSON
scalar URL

A declaração do escalar informa o SDL qual nome usar. A lógica real de serialização, desserialização e validação reside na implementação do servidor — não no arquivo de esquema. Bibliotecas como graphql-scalars oferecem implementações prontas para tipos comuns, para que você não precise escrevê-las do zero.

Use escalares personalizados quando um String é tecnicamente correto, mas semanticamente incorreto. Um campo tipado como DateTime comunica intenção; um campo tipado como String obriga o cliente a adivinhar o formato.

Enums

Enums restringem um campo a um conjunto fixo de valores de string. Eles são mais confiáveis do que strings brutas porque o esquema impõe os valores permitidos no nível de tipo:

enum UserRole {
  ADMIN
  EDITOR
  VIEWER
}

enum PostStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}

Um campo tipado como UserRole nunca retornará uma string inesperada. Um campo tipado como String pode retornar qualquer coisa. Use enums sempre que o conjunto de valores for conhecido, estável e significativo para os clientes — isso torna a inspeção do esquema significativamente mais útil.

Interfaces e Unions

Quando um campo pode retornar tipos diferentes de objetos, o GraphQL oferece duas mecanismos: interfaces e unions.

Interfaces definem um conjunto compartilhado de campos. Tipos que implementam a interface devem incluir esses campos:

interface Node {
  id: ID!
}

type User implements Node {
  id: ID!
  name: String!
}

type Post implements Node {
  id: ID!
  title: String!
}

Unions agrupam tipos sem exigir campos compartilhados. Eles são úteis quando os tipos possíveis não têm nada em comum estruturalmente:

union SearchResult = User | Post | Comment

type Query {
  search(query: String!): [SearchResult!]!
}

Os clientes usam fragmentos inline para lidar com cada tipo em uma união ou interface: ... on User { name }. Se você estiver retornando dados polimórficos, prefira interfaces quando os tipos compartilham campos e unions quando não compartilham.

Diretivas

Diretivas modificam o comportamento no nível de campo ou tipo. Duas estão integradas em cada implementação de GraphQL:

  • @deprecated(reason: "Use newField instead") — marca um campo como descontinuado na inspeção
  • @skip(if: Boolean) e @include(if: Boolean) — condições no lado do cliente em consultas

Você também pode definir diretivas personalizadas para coisas como guardas de autenticação, dicas de limitação de taxa ou anotações de cache. Elas são declaradas no esquema e implementadas no servidor:

directive @auth(requires: UserRole = ADMIN) on FIELD_DEFINITION

type Mutation {
  deleteUser(id: ID!): Boolean! @auth(requires: ADMIN)
}

GraphQL vs REST: Quando Usar Qual

A abordagem schema-first do GraphQL se mostra vantajosa em situações específicas. É a escolha correta quando:

  • Vários clientes (web, móvel, terceiros) precisam de subconjuntos diferentes do mesmo dado
  • Você deseja evoluir a API sem versão — adicione campos livremente, descontinue em vez de remover
  • O domínio é naturalmente em forma de grafo com relações complexas entre entidades
  • Você deseja uma API autodocumentada que os clientes possam explorar por meio da inspeção

O REST ainda é a melhor opção quando:

  • Você está construindo endpoints simples de CRUD com payloads planos e previsíveis
  • A cache HTTP é crítica — as requisições POST do GraphQL não são cacheadas por padrão
  • A equipe é pequena e a superfície da API é estável — o overhead do REST é menor
  • Você está enfrentando o problema N+1 e não deseja configurar o DataLoader para resolver isso

O problema N+1 merece uma pausa. Em um resolutor de GraphQL que recupera posts e cada post de author, uma implementação simples executa uma consulta de banco de dados por post para carregar o autor. Com 50 posts, isso resulta em 51 consultas por uma única requisição. O REST não tem esse problema porque você controla exatamente qual SQL é executado por endpoint. No GraphQL, você o resolve com batching (DataLoader ou equivalente) — é solucionável, mas é mais uma coisa a ser corretamente configurada.

Formatar e Validar seu SDL

Arquivos de esquema acumulam indentação inconsistente, espaçamento incorreto e desvio estrutural à medida que as equipes crescem. Antes de commitar mudanças no esquema, execute-os por meio de um formatador para normalizar o espaçamento, ordenar campos e detectar erros de sintaxe antes que eles atinjam o CI.

O Formatação de Esquema GraphQL on iotools.cloud faz exatamente isso — cole seu SDL, obtenha uma saída limpa e consistentemente formatada com erros de validação exibidos inline. Ele trata esquemas multitypo, escalares personalizados, diretivas e os casos especiais que atrapalham a formatação manual. Útil como uma etapa final antes de commitar ou compartilhar um esquema com outra equipe.

Quer eliminar anúncios? Fique sem anúncios hoje mesmo

Instale nossas extensões

Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida

Ao Extensão do Chrome Ao Extensão de Borda Ao Extensão Firefox Ao Extensão Opera

O placar chegou!

Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!

ANUNCIADO Remover?
ANUNCIADO Remover?
ANUNCIADO Remover?

Notícias com destaques técnicos

Envolver-se

Ajude-nos a continuar fornecendo ferramentas gratuitas valiosas

Compre-me um café
ANUNCIADO Remover?