Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable DateParseHandling on document deserialization

We have documents on DocumentDB that store a date on ISO 8601 format. These dates are stored as strings:

{
  "CreatedOn": "2016-04-15T14:54:40Z",
  "Title": "Some title",
  "id": "xxx-xxx-xxxx-xxx-xxx-xxx"
}

We are using the latest Azure DocumentDB SDK (1.7.0) on a WebAPI that uses ASP.NET Core.

The C# class that maps our documents have the "CreatedOn" property as a string.

public class Item
{
    public string CreatedOn { get; set; }

    public string id { get; set; }

    public string Title { get; set; }
}

The problem is that when we read a document and the SDK deserializes it, it tries to convert it to a DateTime and then back to a string. Resulting in:

{
  "CreatedOn": "15/04/2016 14:54:40",
  "Title": "Some title",
  "id": "xxx-xxx-xxxx-xxx-xxx-xxx"
}

What I need is to the SDK to leave the values untouched. I tried setting the default SerializerSettings to avoid the date parsing:

services.AddMvc().AddJsonOptions(opts =>
{
    opts.SerializerSettings.DateParseHandling = Newtonsoft.Json.DateParseHandling.None;
});

But it didn't work.

I tried using a JsonConverter attribute but the problem is that on the ReadJson override method, the reader already parsed the string value to a DateTime.

class StringJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        reader.Value <-- already a parsed DateTime
    }
}

Any ideas on how to overcome this auto parsing?

like image 520
Matias Quaranta Avatar asked Oct 18 '22 10:10

Matias Quaranta


2 Answers

JSON serializer settings can now be passed straight to DocumentClient constuctors, which allows for the flexibility you required.

like image 195
Guillaume LaHaye Avatar answered Oct 21 '22 21:10

Guillaume LaHaye


Eventually found a workaround, since the JsonSettings are not accesible at this time, I'm using a JsonConverter:

public class StringJsonConverter : JsonConverter
   {
       public override bool CanConvert(Type objectType)
       {
           return true;
       }

       public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
       {
           writer.WriteValue(value.ToString());
       }

       public override bool CanRead
       {
           get { return true; }
       }

       public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
       {
           if (reader.ValueType.Equals(typeof(DateTime)))
           {
               return ((DateTime)reader.Value).ToIso8601Date();
           }
           if (reader.ValueType.Equals(typeof(DateTimeOffset)))
           {
               return ((DateTimeOffset)reader.Value).DateTime.ToIso8601Date();
           }
           return (string)reader.Value;
       }        
   }

With this simple extension:

public static class DateTimeExtensions
{
    private const string DateTimeFormat = "{0}-{1}-{2}T{3}:{4}:{5}Z";

    public static string ToIso8601Date(this DateTime date)
    {
        if (date.Equals(DateTime.MinValue))
        {
            return null;
        }
        return string.Format(
            DateTimeFormat,
            date.Year,
            PadLeft(date.Month),
            PadLeft(date.Day),
            PadLeft(date.Hour),
            PadLeft(date.Minute),
            PadLeft(date.Second));
    }
     private static string PadLeft(int number)
    {
        if (number < 10)
        {
            return string.Format("0{0}", number);
        }

        return number.ToString(CultureInfo.InvariantCulture);
    }
}
like image 34
Matias Quaranta Avatar answered Oct 21 '22 22:10

Matias Quaranta