Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

05 - PATCH - Atualização Parcial

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

PATCH - Atualização Parcial

1. Definição e Semântica

O método HTTP PATCH é definido pela RFC 5789 como o método que solicita a aplicação de modificações parciais ao recurso identificado pela URL alvo. Diferentemente do PUT, que substitui completamente o recurso, o PATCH modifica apenas os campos enviados, preservando os demais.

Características Formais

  • Método: PATCH
  • Seguro: Não (modifica estado do servidor)
  • Idempotente: Não por definição (depende do formato do patch aplicado)
  • Cacheável: Não
  • Corpo na requisição: Sim, obrigatório (documento de patch)
  • Corpo na resposta: Opcional
  • RFC de referência: RFC 5789 (PATCH Method), RFC 6902 (JSON Patch), RFC 7396 (JSON Merge Patch)

Idempotência

PATCH não é idempotente por padrão. A idempotência depende do formato do patch enviado. Por exemplo, uma operação JSON Patch {"op":"add","path":"/tags/-","value":"x"} adiciona um elemento ao array a cada chamada — claramente não idempotente. Já {"op":"replace","path":"/name","value":"Alice"} é idempotente.

PATCH /users/42
Content-Type: application/json

{"name": "Alice Silva"}

Resultado:
- Antes:  {"id":42, "name":"Alice", "email":"alice@x.com", "age":30}
- Depois: {"id":42, "name":"Alice Silva", "email":"alice@x.com", "age":30}

Apenas name foi alterado; email e age foram preservados.

2. PATCH vs PUT

Critério PUT PATCH
Semântica Substituição completa Modificação parcial
Idempotente Sim Não (por padrão)
Campos enviados Todos Apenas os modificados
Campos omitidos Removidos Preservados
RFC 7231 §4.3.4 5789
Formato do corpo Representação do recurso Documento de patch

Exemplo Comparativo

Recurso original: {"id":1, "name":"Bob", "email":"bob@x.com", "age":25}

  • PUT com {"name":"Robert"} → {"id":1, "name":"Robert"} (email e age removidos)
  • PATCH com {"name":"Robert"} → {"id":1, "name":"Robert", "email":"bob@x.com", "age":25}

3. Formatos de Patch

PATCH não define um formato único para o corpo; o Content-Type determina o formato utilizado. Os dois principais são JSON Patch e JSON Merge Patch.

JSON Patch (RFC 6902)

Formato estruturado com operações explícitas. Cada operação tem op, path (JSON Pointer) e value.

PATCH /users/42 HTTP/1.1
Content-Type: application/json-patch+json

[
  {"op":"replace","path":"/email","value":"alice.silva@exemplo.com"},
  {"op":"remove","path":"/tempField"},
  {"op":"add","path":"/tags/-","value":"premium"},
  {"op":"move","from":"/oldAddress","path":"/address"},
  {"op":"copy","from":"/name","path":"/alias"},
  {"op":"test","path":"/version","value":3}
]

Operações suportadas: add (adiciona valor em path), remove, replace, move (de from para path), copy (de from para path), test (valida valor; falha retorna 412 — útil para concorrência otimista dentro do patch).

JSON Merge Patch (RFC 7396)

Formato simplificado: um JSON com os campos a sobrescrever. Campos com valor null indicam remoção.

PATCH /users/42 HTTP/1.1
Content-Type: application/merge-patch+json

{"name": "Alice Silva", "email": null, "preferences": {"theme": "dark"}}

Resultado: name substituído, email removido (null), preferences.theme substituído, demais campos preservados.

Comparativo

Critério JSON Patch (6902) JSON Merge Patch (7396)
Content-Type application/json-patch+json application/merge-patch+json
Estrutura Array de operações Objeto JSON
Complexidade Alta Baixa
Suporte a arrays Sim (índices) Limitado (substitui array inteiro)
Remoção de campo Operação remove explícita Valor null
Idempotência Operações específicas são Sim (substituição de campos)
Diff granular Sim Não

4. Headers Importantes

  • Content-Type: Define o formato do patch. Obrigatório distinguir application/json-patch+json de application/merge-patch+json.
  • If-Match: Concorrência otimista via ETag (If-Match: "v3"). Retorna 412 Precondition Failed se ETag atual não for a esperada (alguém modificou antes).
  • Accept-Patch: Header de resposta a OPTIONS indicando formatos aceitos: Accept-Patch: application/json-patch+json, application/merge-patch+json.

5. Códigos de Resposta Típicos

Status Significado Quando usar
200 OK Sucesso com corpo PATCH aplicado, retorna recurso atualizado
204 No Content Sucesso sem corpo PATCH aplicado, sem payload de retorno
400 Bad Request Sintaxe inválida JSON malformado, operações inválidas
401 Unauthorized Falta autenticação Token ausente ou inválido
403 Forbidden Sem permissão Autenticado, mas sem direito de escrita
404 Not Found Recurso não existe PATCH em URL inexistente
409 Conflict Conflito de estado Operação test falhou, versão incompatível
412 Precondition Failed If-Match falhou ETag não corresponde
415 Unsupported Media Type Content-Type não suportado Servidor só aceita merge-patch, recebeu json-patch
422 Unprocessable Entity Operação semanticamente inválida Path inexistente em remove, índice de array inválido

6. Exemplos Práticos

curl — Merge Patch Simples

curl -X PATCH https://api.exemplo.com/users/42 \
  -H "Content-Type: application/merge-patch+json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"Alice Silva","age":31}'

curl — JSON Patch com Múltiplas Operações

curl -X PATCH https://api.exemplo.com/users/42 \
  -H "Content-Type: application/json-patch+json" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'If-Match: "v3"' \
  -d '[
    {"op":"replace","path":"/email","value":"alice.silva@exemplo.com"},
    {"op":"add","path":"/tags/-","value":"vip"},
    {"op":"remove","path":"/tempData"},
    {"op":"test","path":"/version","value":3}
  ]'

Python (requests)

import requests
r = requests.patch(
    "https://api.exemplo.com/users/42",
    json={"name": "Alice Silva", "age": 31},
    headers={"Content-Type": "application/merge-patch+json",
             "Authorization": "Bearer " + token},
)
print(r.status_code, r.json())

7. Boas Práticas em APIs REST

  • Suporte a ambos os formatos: Implemente JSON Patch e Merge Patch; o cliente escolhe via Content-Type.
  • Validação de operações: Verifique path existe para replace/remove, índice de array válido para add, tipos compatíveis para value.
  • Transações atômicas: Aplique todas as operações como transação; se uma falha, nenhuma é aplicada (retorne 409 ou 422).
  • Retorno do recurso atualizado: Em respostas 200 OK, inclua o recurso completo atualizado.
  • Idempotency-Key: Aceite header Idempotency-Key para garantir que retries não apliquem patches duplicados (cache 24h).

8. Erros Comuns

Erro Causa Correção
Usar PATCH como PUT Substituição completa por engano Documentar diferença na API
Não validar Content-Type Servidor assume merge-patch sempre Aceitar ambos os formatos
Aplicar operações não atômicas Falha parcial deixa estado inconsistente Usar transação no banco
Perda de dados por campo null Merge patch com null inesperado Validar schema antes de aplicar

9. Resumo Técnico

Atributo Valor
Método PATCH
RFC 5789
Idempotente Não (por padrão)
Seguro Não
Cacheável Não
Corpo obrigatório Sim
Formatos principais JSON Patch (6902), JSON Merge Patch (7396)
Sucessos típicos 200, 204
Concorrência ETag + If-Match

10. Conclusão

O método PATCH é o mecanismo HTTP para atualização parcial de recursos, complementando o PUT (substituição completa). A escolha entre JSON Patch e JSON Merge Patch depende do nível de controle necessário: JSON Patch oferece operações granulares (add, remove, move, test), enquanto Merge Patch é mais simples e idiomático para diffs de objetos JSON. Embora não seja idempotente por padrão, operações específicas podem ser. O uso de If-Match para concorrência otimista e Idempotency-Key para retries é essencial em APIs REST modernas. PATCH é a escolha correta para formulários de edição parcial, atualização de preferências e qualquer operação onde apenas alguns campos mudam.