1
resposta

[Projeto] Desserializando Filmes - Conversor automático

Gostaria de observar aqui que no JSON dos Filmes as informações do ANO e a NOTA DO IMDB estão entre aspas, o que acaba vindo para o C# como sendo STRING ao invés de INT e DECIMAL(ou DOUBLE) respectivamente, portanto foi preciso converter essas informações para o seu respectivo tipo correto.

Primeiro eu pensei em ter uma variável a mais para fazer o int.Parse e o double.Parse, mas vi que seria algo muito manual e que teria que fazer isso para vários campos caso o JSON, por exemplo, tivesse diversos campos na mesma condição. Então pesquisei uma forma de fazer essa conversão antes de atribuir o valor do campo do JSON na minha variável dentro da classe, e foi aí que descobri (com a ajuda do Gemini) a possibilidade de criar um conversor genérico automático.

Achei muito legal esse conversor, apesar de não entender 100% dele ainda porque ainda não exploramos muitos recursos de JSON no curso ainda. Enfim, mesmo assim fiz e segue abaixo como ficou o exercício.

Classe Filme:

using System.Reflection.Metadata.Ecma335;
using System.Text.Json.Serialization;
namespace Filmes.Modelos;
internal class Filme
{
    [JsonPropertyName("title")]
    public string Nome { get; set; }

    [JsonPropertyName("year")]
    [JsonConverter(typeof(StringToNumberConverter<int>))]
    public int? Ano { get; set; }

    [JsonPropertyName("imDbRating")]
    [JsonConverter(typeof(StringToNumberConverter<decimal>))]
    public decimal? Nota { get; set; }

    public void ExibirDetalhesDoFilme()
    {
        Console.WriteLine($"Nome do filme: {Nome}");
        Console.WriteLine($"Ano de lançamento: {Ano}");
        Console.WriteLine($"Nota IMDB: {Nota}");
    }
}

Classe StringToNumberConverter (Conversor):

using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Filmes.Modelos;
internal class StringToNumberConverter<T> : JsonConverter<T> where T : IConvertible
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.String)
        {
            var stringValue = reader.GetString();
            if (string.IsNullOrEmpty(stringValue))
            {
                return default;
            }
            // Converte a string para o tipo T
            return (T)Convert.ChangeType(stringValue, typeof(T), CultureInfo.InvariantCulture);
        }
        else if (reader.TokenType == JsonTokenType.Number)
        {
            // Se já for um número, usa a conversão padrão
            return JsonSerializer.Deserialize<T>(ref reader, options);
        }

        throw new JsonException($"Não foi possível converter o valor para o tipo {typeof(T).Name}");
    }

    public override void Write (Utf8JsonWriter writer, T value, JsonSerializerOptions options)
    {
        // Implementaçãopara escrita (serialização), se necessário
    }
}

Program Filmes:

using Filmes.Modelos;
using System.Text.Json;

using (HttpClient client = new HttpClient())
{
    try
    {
        string resposta = await client.GetStringAsync("https://raw.githubusercontent.com/ArthurOcFernandes/Exerc-cios-C-/curso-4-aula-2/Jsons/TopMovies.json");
        //Console.WriteLine(resposta);
        var filmes = JsonSerializer.Deserialize<List<Filme>>(resposta);
        Console.WriteLine($"Existem {filmes.Count} filmes na lista.\n");
        Console.WriteLine("Pressione ENTER para exibir os detalhes dos filmes...");
        Console.ReadKey();
        Console.WriteLine();
        filmes[1].ExibirDetalhesDoFilme();
    } 
    catch (Exception ex)
    {
        Console.WriteLine($"Erro: {ex}");
    }
}
1 resposta

Olá Fábio! Tudo bem?

Que legal ver você explorando a desserialização de JSONs e criando soluções para converter tipos de dados de forma automática.

O uso de um conversor genérico como o StringToNumberConverter é uma abordagem bastante eficiente para lidar com situações em que os dados vêm como strings, mas são necessários em outros tipos numéricos.

Seu código está bem estruturado e a ideia de usar o JsonConverter para converter strings para tipos numéricos é uma excelente solução para evitar a conversão manual em cada campo. Isso torna o código mais limpo e fácil de manter, especialmente se você estiver lidando com JSONs grandes ou complexos.

Aqui está um exemplo prático de como você poderia usar esse conversor em outro contexto, como ao desserializar uma classe Pais:

internal class Pais
{
    [JsonPropertyName("name")]
    public string Nome { get; set; }

    [JsonPropertyName("population")]
    [JsonConverter(typeof(StringToNumberConverter<long>))]
    public long? Populacao { get; set; }

    [JsonPropertyName("area")]
    [JsonConverter(typeof(StringToNumberConverter<double>))]
    public double? Area { get; set; }

    public void ExibirDetalhesDoPais()
    {
        Console.WriteLine($"Nome do país: {Nome}");
        Console.WriteLine($"População: {Populacao}");
        Console.WriteLine($"Área: {Area} km²");
    }
}

Ao seguir essa abordagem, você pode facilmente aplicar o mesmo conversor a outras classes que precise desserializar, como Carro e Livro, conforme os desafios propostos.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.