Runtime: System.Text.Json doesn't deserialize ASP.NET JSON date

Created on 6 Sep 2019  路  3Comments  路  Source: dotnet/runtime

System.Text.Json fails to deserialize ASP.NET JSON dates such as "/Date(1530144000000+0530)/" which seems silly as there are still microsoft apis using this date format. specifically the O365 Service Health Api.

area-System.Text.Json

Most helpful comment

For anyone blocked by this, here's a NuGet package with a couple converters (JsonMicrosoftDateTimeConverter & JsonMicrosoftDateTimeOffsetConverter) based on the code posted above by @scalablecory: Macross.Json.Extensions

Supports DateTime, Nullable<DateTime>, DateTimeOffset, & Nullable<DateTimeOffset> types in the old /Date(...)/ Microsoft format.

All 3 comments

We made a conscious decision to not support this non-standard format. You can, however use a custom converter to add your own support for this:

```c#
class Program
{
static void Main(string[] args)
{
var opts = new JsonSerializerOptions();
opts.Converters.Add(new FunnyDateConverter());

    string json = JsonSerializer.Serialize(new
    {
        Date = DateTimeOffset.Now
    }, options: opts);

    Console.WriteLine(json);
}

}

sealed class FunnyDateConverter : JsonConverter
{
static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new Regex("^/Date\(([^+-]+)([+-])(\d{2})(\d{2})\)/$", RegexOptions.CultureInvariant);

public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    if (typeToConvert != typeof(DateTimeOffset))
    {
        throw new ArgumentException($"Unexpected type '{typeToConvert}'.");
    }

    string formatted = reader.GetString();
    Match match = s_regex.Match(formatted);

    if (
            !match.Success
            || !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
            || !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
            || !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
    {
        throw new Exception("Unexpected value format, unable to parse DateTimeOffset.");
    }

    int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
    TimeSpan utcOffset = new TimeSpan(hours * sign, minutes * sign, 0);

    return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}

public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
    long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
    TimeSpan utcOffset = value.Offset;

    string formatted = FormattableString.Invariant($"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
    writer.WriteStringValue(formatted);
}

}
```

cc @steveharter, @JamesNK

For anyone blocked by this, here's a NuGet package with a couple converters (JsonMicrosoftDateTimeConverter & JsonMicrosoftDateTimeOffsetConverter) based on the code posted above by @scalablecory: Macross.Json.Extensions

Supports DateTime, Nullable<DateTime>, DateTimeOffset, & Nullable<DateTimeOffset> types in the old /Date(...)/ Microsoft format.

Was this page helpful?
0 / 5 - 0 ratings