You're correct that CanConvert
only deals with Types and so you cannot make the converter conditional on specific JSON values. However, you said that your desired behavior is that the conversion from string to TimeSpan
is not performed if the format does not exactly match hh:mm:ss
, which I take to mean that you would expect the TimeSpan
in your deserialized object to have a default value of zero, correct? In that case, you could just make the ReadJson
method in the converter do the same thing, i.e. return a default TimeSpan
if the format does not exactly match:
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public string TimeSpanFormat { get; set; } = @"hh\:mm\:ss";
public TimeSpan DefaultTimeSpan { get; set; } = TimeSpan.Zero;
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string timeString = reader.GetString();
if (TimeSpan.TryParseExact(timeString, TimeSpanFormat, CultureInfo.InvariantCulture, out TimeSpan timeSpan))
{
return timeSpan;
}
return DefaultTimeSpan;
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(TimeSpanFormat));
}
}
Here's a short program to demonstrate usage:
public static void Main(string[] args)
{
string json = @"
{
""TimeSpan1"": ""15:46:03"",
""TimeSpan2"": ""3:04""
}";
var options = new JsonSerializerOptions();
options.Converters.Add(new TimeSpanConverter());
var foo = JsonSerializer.Deserialize<Foo>(json, options);
Console.WriteLine(foo.TimeSpan1.ToString(@"hh\:mm\:ss"));
Console.WriteLine(foo.TimeSpan2.ToString(@"hh\:mm\:ss"));
}
public class Foo
{
public TimeSpan TimeSpan1 { get; set; }
public TimeSpan TimeSpan2 { get; set; }
}
Output:
15:46:03
00:00:00