Vinicius Quinafelex Alves

🌐English version

[C#] Desserializar JSON em uma interface com JsonConverter

No C#, interfaces não podem ser instanciada diretamente. Para desserializar interfaces, é preciso escolher uma classe que implemente a interface, para que o desserializador consiga alimentar as propriedades correspondentes.

No exemplo abaixo, o código verifica o atributo Type dentro do JSON para escolher qual classe deve ser instanciada.

Exemplo de JSON

{
    "FirstValue": {
        "Type": "TypeA",
        "StringContent": "Example"
    },
    "SecondValue": {
        "Type": "TypeB",
        "IntegerContent": 123
    }
}

Estrutura de desserialização

public interface ICustomInterface 
{ 
    string Type { get; }
}

public class DeserializationResult
{
    public ICustomInterface? FirstValue { get; set; }
    public ICustomInterface? SecondValue { get; set; }
}

Múltiplas implementações de interface

public class ImplementationTypeA : ICustomInterface 
{ 
    public string Type { get; set; }
    public string StringContent { get; set; }
}

public class ImplementationTypeB : ICustomInterface 
{ 
    public string Type { get; set; }
    public int IntegerContent { get; set; }
}

Implementando o CustomJsonConverter

using System.Text.Json;

public class CustomJsonConverter : JsonConverter<ICustomInterface?>
{
    public override ICustomInterface? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var node = JsonNode.Parse(ref reader);
        var type = node!["Type"]?.GetValue<string?>();

        if(type == "TypeA")
            return node.Deserialize<ImplementationTypeA>();

        if(type == "TypeB")
            return node.Deserialize<ImplementationTypeB>();

        return null;
    }

    public override void Write(Utf8JsonWriter writer, ICustomInterface? value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, (object?)value, options);
    }
}

Usando o JsonConverter

using System.Text.Json;
            
public void ExecuteDeserialization(string json) 
{
    var jsonOptions = new JsonSerializerOptions();
    jsonOptions.Converters.Add(new CustomJsonConverter());

    var resultInstance = JsonSerializer.Deserialize<DeserializationResult>(json, jsonOptions);

    var serializedJson = JsonSerializer.Serialize(resultInstance, jsonOptions);
}