[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);
}