I'm trying to deserialize a snippet of JSON that looks something like this:
{
"timePoints": [ "2020", "2020-1-9", "2020-4-1" ]
}
The idea here is that we will allow either a fully qualified date, or just a year which will be converted to a nominal date. So I created a custom JsonConverter to handle this field:
public class Foo
{
[JsonConverter(typeof(TimePointConverter))]
public IEnumerable<DateTime> TimePoints { get; set; }
}
public class TimePointConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
reader.DateParseHandling = DateParseHandling.None;
var obj = JArray.ReadFrom(reader);
var points = obj.Select(x =>
{
if (!DateTime.TryParse(x.ToString(), out var date))
{
if (int.TryParse(x.ToString(), out int year) && year > 0)
{
date = new DateTime(year, 10, 1); // qtr 4
}
else
{
throw new FormatException($"Unable to parse date: {x.ToString()} is invalid.");
}
}
return date;
});
return points.Any() ? points.ToArray() : null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
But the problem is that JArray.ReadFrom
will automatically try to interpret 2020-1-9
and 2020-4-1
as dates. But since 2020
isn't a date, it just ignores it altogether. So I end up with obj
being an array of two dates silently ignore the third item. How do I stop this behavior? I want it to read these as strings, not as dates? DateParseHandling.None
seems to have no effect at all.
Update: Turned out I was looking in the wrong place. This was being serialized somewhere else before it even got to the application I was looking at and that was removing the non-date item. Closing this question now...