Pular para o conteúdo
.NETMoldando os campos retornados
Módulo 05Consultas Avançadas

Moldando os campos retornados

avancado 45 min de leitura·Atualizado · .NET 9
Resumo

Data shaping permite ao cliente pedir apenas os campos que precisa (fields=nome,preco), reduzindo o payload. Implementamos com reflexão e um dicionário de propriedades (ExpandoObject).

1. Objetivos de Aprendizagem#

  • Explicar o benefício de data shaping.
  • Implementar shaping por reflexão sobre o DTO.
  • Lidar com serialização XML/JSON do resultado moldado.

2. Pré-requisitos#

  • Ordenação dinâmica (Módulo 33).

3. Conceito#

Data shaping devolve subconjuntos de campos por objeto conforme o cliente pede. O porquê: economizar banda e permitir que diferentes clientes obtenham exatamente o que consomem, sem múltiplos endpoints. Implementamos com reflexão: lemos as propriedades solicitadas do DTO e montamos um ExpandoObject com apenas elas.

4. Mão na Massa#

4.1. Setup#

Sem pacotes novos.

4.2. Implementação Passo a Passo#

  1. Serviço de shaping:
C#
using System.Dynamic;
using System.Reflection;

public class DataShaper<T> where T : class
{
    private readonly PropertyInfo[] _properties =
        typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    public IEnumerable<ExpandoObject> ShapeData(IEnumerable<T> entities, string? fields)
    {
        var required = GetRequiredProperties(fields);
        return entities.Select(e => FetchData(e, required));
    }

    private IEnumerable<PropertyInfo> GetRequiredProperties(string? fields)
    {
        if (string.IsNullOrWhiteSpace(fields)) return _properties;

        var wanted = fields.Split(',', StringSplitOptions.RemoveEmptyEntries)
                           .Select(f => f.Trim());
        return _properties.Where(p =>
            wanted.Contains(p.Name, StringComparer.OrdinalIgnoreCase));
    }

    private static ExpandoObject FetchData(T entity, IEnumerable<PropertyInfo> props)
    {
        var shaped = new ExpandoObject();
        foreach (var p in props)
            ((IDictionary<string, object?>)shaped)[p.Name] = p.GetValue(entity);
        return shaped;
    }
}
  1. Registro e uso:
C#
builder.Services.AddScoped<DataShaper<ProdutoDto>>();
// no serviço/controller:
var shaped = _shaper.ShapeData(produtosDto, parameters.Fields);
return Ok(shaped);

4.3. Executando#

Shell
curl "http://localhost:5000/api/produtos?fields=nome,preco"

5. Exemplo Completo#

Campos inexistentes são ignorados; sem fields, retornamos o DTO completo. O ExpandoObject serializa naturalmente em JSON.

6. Boas Práticas e Armadilhas#

FaçaEvite
Moldar sobre o DTO, não sobre a entidadeExpor campos internos via reflexão na entidade
Ignorar campos desconhecidosLançar exceção para cada campo inválido
Usar shaping só onde há ganho realComplicar todos os endpoints com shaping
Atenção

shaping quebra a tipagem forte da resposta (vira ExpandoObject), dificultando documentação (Swagger) e clientes tipados. Use com parcimônia e documente bem.

7. Segurança e Produção#

  • Como refletimos sobre o DTO (não a entidade), campos sensíveis nunca entram no shaping.
  • XML shaping é mais complexo (o ExpandoObject não serializa bem em XML) — trate esse cenário à parte se oferecer XML.

8. Exercícios#

  • Fácil: peça só id,nome e valide o resultado.
  • Médio: garanta que o campo chave (Id) esteja sempre presente.
  • Desafio: resolva a serialização XML do objeto moldado.

9. Resumo#

Data shaping devolve apenas os campos pedidos usando reflexão sobre o DTO e ExpandoObject, economizando banda ao custo de tipagem forte na resposta.

10. Próximos Passos#

Módulo 35: HATEOAS, elevando a API ao nível 3 de maturidade REST.

11. Referências#

34-01 — Moldando os campos retornados | Curso ASP.NET Core