Novidades do .NET 7: melhorias na serialização JSON em cenários de polimorfismo

Renato Groffe
4 min readAug 8, 2022

--

Princípios como herança e polimorfismo são aspectos centrais dentro da disciplina de Orientação a Objetos, constituindo noções importantíssimas em cenários que demandem reaproveitamento de código e uma melhor estruturação de projetos de software. Muitas bibliotecas e funcionalidades são inclusive projetadas tomando por base estes conceitos, o que acaba por exigir um claro entendimento dos mesmos.

O próprio .NET 7 levou em conta os conceitos de herança e polimorfismo, em melhorias envolvendo processos de serialização e desserialização com recursos do namespace System.Text.Json. É o que mostrarei neste novo artigo, que dá continuidade à série de novidades do .NET 7.

Caso queira ficar por dentro dos conteúdos anteriores sobre .NET 7 publicados aqui no blog, acesse o link a seguir:

.NET 7 - Guia de Referência: artigos, vídeos e exemplos de utilização

Supondo as implementações a seguir, em que a classe Aluno herda de Pessoa:

Considerando a serialização de uma instância de Aluno tratada como se fosse uma referência para Pessoa, notaremos que ao final deste processo a variável indicada por pessoa2 é agora uma instância de Pessoa (e não Aluno). Isto aconteceu porque o conteúdo associado à propriedade Curso foi descartado durante a serialização (resultado destacado em vermelho no print):

Numa versão refatorada do exemplo anterior o atributo JsonDerivedType foi associado à classe Pessoa, com a indicação de que instâncias de Aluno correspondem a um tipo derivado que deve ser considerado na serialização:

Isto ainda não resolverá a questão da desserialização (o conteúdo da propriedade Curso foi perdido, já que geramos uma instância de Pessoa), mas podemos notar que a etapa de serialização já reconheceu o tipo da variável pessoa2 como Aluno (variável jsonPessoa2):

Podemos solucionar essa questão preenchendo o atributo typeDiscriminator de JsonDerivedType (namespace System.Text.Json.Serialization), com um identificador específico para cada tipo (a string informada deve representar um valor único):

A serialização acrescentará o campo $type a cada resultado, estando associado ao mesmo o valor de typeDiscriminator. Com isto a desserialização de jsonPessoa2 produzirá uma instância de Aluno:

É possível até mesmo customizar o nome do campo que corresponde ao typeDiscriminator, através do uso do atributo JsonPolymorphic (namespace System.Text.Json.Serialization) e preenchimento de sua propriedade TypeDiscriminatorPropertyName:

Para este exemplo definimos $class como valor do typeDiscriminator, conforme é possível observar nos resultados destacados na imagem a seguir:

Na listagem a seguir temos outras alternativas de uso dos atributos JsonDerivedType e JsonPolymorphic:

  • Valores int também podem ser informados em typeDiscriminator, como indicado nas linhas 5 e 6 para os tipos Veiculo e Carro;
  • A classe CarroCorrida não foi associada a nenhuma declaração com o atributo JsonDerivedType. Isto poderia acarretar num erro de serialização ao utilizarmos o tipo Veiculo. Para resolver este problema podemos configurar no atributo JsonPolymorphic o valor da propriedade UnknownDerivedTypeHandling com o enumerator JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor, que determina que as regras de serialização assumirão as configurações do ancestral mais próximo (Carro);
  • Outras possibilidades para JsonUnknownDerivedTypeHandling são FallBackToBaseType (em que se assumem as configurações do tipo no topo da hierarquia, que neste exemplo seria Veiculo) e FailSerialization (comportamento default, lançando uma exceção caso não haja mapeamento com JsonDerivedType).

Já na próxima listagem temos testes envolvendo serialização e desserialização com os tipos Veiculo, Carro e CarroCorrida. Pelas regras definidas na listagem anterior a instância de CarroCorrida será serializada/desserializada como uma referência do tipo Carro:

É o que demonstram os resultados a seguir:

Os testes apresentados aqui foram disponibilizados em um repositório do GitHub:

https://github.com/renatogroffe/DotNet7-Preview6-ConsoleApp-JsonSerialization-Polymorphism

Caso achem útil a solução, peço por favor um ⭐️ no repositório apoiando. Fica também o convite para que vocês me sigam lá!

E finalizo este artigo com um convite…

Segunda 15/08 às 21:00 horário de Brasília — teremos mais um evento online e gratuito no canal Canal .NET.

Esta nova live trará dicas, truques e alternativas úteis para o desenvolvimento Back-End e de APIs REST com .NET 6, C#, ASP.NET Core e Azure Functions. Ao longo da apresentação será coberto o uso de diferentes frameworks, serviços na nuvem, mensageria e boas práticas de forma a facilitar e tornar mais dinâmica a implementação de soluções baseadas na plataforma .NET no seu dia a dia.

Teremos também algumas novidades do Visual Studio 2022, .NET 7 e do C# 11 demonstradas na prática!

Para participar faça sua inscrição no link a seguir, a transmissão acontecerá via YouTube:

https://bit.ly/live-backend-dotnet-ago-2022

--

--

Renato Groffe

Microsoft Most Valuable Professional (MVP), Multi-Plataform Technical Audience Contributor (MTAC), Software Engineer, Technical Writer and Speaker