Pular para o conteúdo
.NETAtualização parcial com JSON Patch
Módulo 04CRUD Completo e Validação

Atualização parcial com JSON Patch

intermediario 35 min de leitura·Atualizado · .NET 9
Resumo

PATCH atualiza apenas parte de um recurso. Com o formato JSON Patch (RFC 6902), o cliente envia uma lista de operações (replace, add, remove) aplicadas sobre um DTO, com validação após o patch.

1. Objetivos de Aprendizagem#

  • Diferenciar PATCH de PUT.
  • Implementar PATCH com JsonPatchDocument<T>.
  • Aplicar o patch a um DTO e revalidar o ModelState.

2. Pré-requisitos#

  • Atualização com PUT (Módulo 25).

3. Conceito#

PATCH aplica uma modificação parcial. O formato JSON Patch descreve operações:

JSON
[
  { "op": "replace", "path": "/preco", "value": 129.9 },
  { "op": "replace", "path": "/nome", "value": "Mouse Ultra" }
]

O porquê de aplicar ao DTO (e não à entidade): controlar quais campos são alteráveis e revalidar antes de persistir.

4. Mão na Massa#

4.1. Setup#

Shell
dotnet add Catalog.Api package Microsoft.AspNetCore.Mvc.NewtonsoftJson
dotnet add Catalog.Api package Microsoft.AspNetCore.JsonPatch

Habilite o Newtonsoft (necessário para JSON Patch):

C#
builder.Services.AddControllers()
    .AddNewtonsoftJson();
Nota

o input formatter de JSON Patch depende do Newtonsoft.Json. Ative-o apenas para suportar application/json-patch+json; o restante da API pode continuar com System.Text.Json conforme sua configuração.

4.2. Implementação Passo a Passo#

  1. Serviço: retorna o par (DTO para patch, entidade rastreada):
C#
public async Task<(ProdutoForUpdateDto dto, Produto entity)> GetForPatchAsync(Guid categoriaId, Guid id)
{
    var produto = await _repo.Produto.GetByIdAsync(categoriaId, id, trackChanges: true)
        ?? throw new ProdutoNotFoundException(id);
    var dto = _mapper.Map<ProdutoForUpdateDto>(produto);
    return (dto, produto);
}

public async Task SavePatchAsync(ProdutoForUpdateDto dto, Produto entity)
{
    _mapper.Map(dto, entity);
    await _repo.SaveAsync();
}
  1. Controller:
C#
[HttpPatch("{id:guid}")]
public async Task<IActionResult> Patch(Guid categoriaId, Guid id,
    [FromBody] JsonPatchDocument<ProdutoForUpdateDto> patchDoc)
{
    if (patchDoc is null) return BadRequest("patchDoc não pode ser nulo.");

    var (dto, entity) = await _service.Produto.GetForPatchAsync(categoriaId, id);
    patchDoc.ApplyTo(dto, ModelState);

    TryValidateModel(dto);                 // revalida após o patch
    if (!ModelState.IsValid) return UnprocessableEntity(ModelState);

    await _service.Produto.SavePatchAsync(dto, entity);
    return NoContent();
}

4.3. Executando#

Shell
curl -i -X PATCH http://localhost:5000/api/categorias/{catId}/produtos/{id} \
  -H "Content-Type: application/json-patch+json" \
  -d '[{"op":"replace","path":"/preco","value":129.9}]'

5. Exemplo Completo#

O fluxo: buscar entidade rastreada → mapear para DTO → ApplyTo no DTO com ModelStateTryValidateModel → mapear DTO de volta para a entidade → salvar.

6. Boas Práticas e Armadilhas#

FaçaEvite
Passar o ModelState ao ApplyToIgnorar erros de patch (paths inválidos)
Revalidar com TryValidateModel após aplicarPersistir um DTO possivelmente inválido
Aplicar o patch ao DTO, não à entidadeDeixar o cliente alterar campos internos via path
Atenção

aplicar JSON Patch diretamente na entidade permite ao cliente alterar campos não previstos (/categoriaId, /id). Sempre patch no DTO restrito.

7. Segurança e Produção#

  • JSON Patch é poderoso; limite os paths permitidos usando um DTO enxuto.
  • Habilitar Newtonsoft globalmente muda a serialização — teste os endpoints existentes após ativar.

8. Exercícios#

  • Fácil: faça um patch que altere só o nome.
  • Médio: retorne 422 quando o patch tornar o preço negativo (validação).
  • Desafio: suporte JSON Patch e JSON Merge Patch (RFC 7386) no mesmo recurso.

9. Resumo#

PATCH faz atualização parcial via JSON Patch aplicado a um DTO restrito, com revalidação de ModelState. Isso mantém segurança e integridade, ao contrário de aplicar o patch direto na entidade.

10. Próximos Passos#

Módulo 27: validação — ModelState, atributos e validação por verbo.

11. Referências#

26-01 — Atualização parcial com JSON Patch | Curso ASP.NET Core