Vinicius Quinafelex Alves

🌐Ler em português

[C#] Deserialize JSON to an interface with JsonConverter

On C#, interfaces cannot be instantiated directly. To deserialize interfaces, you need to choose a class that implements that interface, so the deserializer can fill the corresponding properties.

Below there's an example where the code checks an attribute Type inside the JSON to determine what class should be instanciated.

JSON Example

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

Deserialized structure

public interface ICustomInterface 
{ 
    string Type { get; }
}

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

Multiple interface implementations

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

Implementing the 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);
    }
}

Consuming the 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);
}