在文档反序列化时禁用 DateParseHandling

Disable DateParseHandling on document deserialization

我们在 DocumentDB 上有存储 ISO 8601 format 日期的文档。这些日期存储为字符串:

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

我们在使用 ASP.NET Core.

WebAPI 上使用最新的 Azure DocumentDB SDK (1.7.0)

映射我们文档的 C# class 将 "CreatedOn" 属性 作为 字符串

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

    public string id { get; set; }

    public string Title { get; set; }
}

问题是,当我们读取文档并且 SDK 反序列化它时,它会尝试将其转换为 DateTime 然后 back 字符串 。结果:

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

我需要让 SDK 保持值不变。我尝试设置默认的 SerializerSettings 以避免日期解析:

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

但是没有用。

我尝试使用 JsonConverter 属性,但问题是在 ReadJson 覆盖方法上,reader 已经将字符串值解析为 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
    }
}

关于如何克服这种自动解析的任何想法?

最终找到了解决方法,因为此时JsonSettings are not accesible,我使用的是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;
       }        
   }

有了这个简单的扩展:

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);
    }
}

JSON 序列化程序设置现在可以直接传递给 DocumentClient constuctors,这允许您需要的灵活性。