ASP.NET Core 5 doesn't respect neither JsonConverter nor TypeConverter

Viewed 416

The title is pretty self explanatory. ASP.NET Core 5 doesn't respect neither the JsonConverter nor the TypeConverter.

The symbols e.g. "TRX/USDT" should be split by / and converted to new Symbol("TRX", "USDT") as I already did that. Basically, I want services.Configure<BacktestOptions>(hostingContext.Configuration.GetSection(BacktestOptions.Backtest)) to resolve it automatically.

public IReadOnlyCollection<string> Symbols { get; set; } works fine, but public IReadOnlyCollection<Symbol> Symbols { get; set; } doesn't, because it doesn't recognize the converter class.

This question Asp.Net Core 3.1 Appsettings not respecting JsonConverter, the guy who answered it, states that TypeConverter should work.

appsettings.json

{
  "Backtest": {
    "StartBalance": 1000, 
    "StakeCurrency": "USDT",
    "Symbols": [ "TRX/USDT", "BTC/USDT", "ETH/USDT" ]
  }
}

Snippet

public class Symbol
{
    public Symbol()
    {
    }

    public Symbol(string baseAsset, string quoteAsset)
    {
        BaseAsset = baseAsset;
        QuoteAsset = quoteAsset;
    }

    public string BaseAsset { get; set; }
    public string QuoteAsset { get; set; }
}

public class BacktestOptions
{
    public const string Backtest = "Backtest";
    
    [Required]
    [Range(100, 50000)]
    public decimal StartBalance { get; set; }
    
    [Required]
    [RegularExpression(@"^[a-zA-Z]+$")]
    public string StakeCurrency { get; set; }
    
    [Required]
    [TypeConverter(typeof(SymbolConverter))]
    public IReadOnlyCollection<Symbol> Symbols { get; set; }
}

public class SymbolConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context,
        Type sourceType)
    {
        if (sourceType == typeof(string))
        {
            return true;
        }

        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context,
        CultureInfo culture, object value)
    {
        if (value is string v)
        {
            var parts = v.Split('/');

            return new Symbol(parts[0], parts[1]);
        }

        return base.ConvertFrom(context, culture, value);
    }
}

Additionally, JsonConverter example

public class SymbolConverter : JsonConverter<IReadOnlyCollection<Symbol>>
{
    public override IReadOnlyCollection<Symbol> Read(ref Utf8JsonReader reader, Type typeToConvert,
        JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.StartArray)
        {
            var values = JsonSerializer.Deserialize<string[]>(ref reader, options);

            var symbols = values.Select(value => value.Split('/')).Select(parts => new Symbol(parts[0], parts[1])).ToList();

            return new ReadOnlyCollection<Symbol>(symbols);
        }

        return null;
    }

    public override void Write(Utf8JsonWriter writer, IReadOnlyCollection<Symbol> value, JsonSerializerOptions options)
        => throw new NotImplementedException();
}
0 Answers
Related