在文档反序列化时禁用 DateParseHandling

Mat*_*nta 5 azure-cosmosdb

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

{
  "CreatedOn": "2016-04-15T14:54:40Z",
  "Title": "Some title",
  "id": "xxx-xxx-xxxx-xxx-xxx-xxx"
}
Run Code Online (Sandbox Code Playgroud)

我们在使用 ASP.NET Core 的 WebAPI上使用最新的Azure DocumentDB SDK (1.7.0) 。

映射文档的 C# 类具有字符串形式的“CreatedOn”属性。

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

    public string id { get; set; }

    public string Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我们读取文档并且 SDK 对其进行反序列化时,它会尝试将其转换为DateTime,然后再转换string。导致:

{
  "CreatedOn": "15/04/2016 14:54:40",
  "Title": "Some title",
  "id": "xxx-xxx-xxxx-xxx-xxx-xxx"
}
Run Code Online (Sandbox Code Playgroud)

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

services.AddMvc().AddJsonOptions(opts =>
{
    opts.SerializerSettings.DateParseHandling = Newtonsoft.Json.DateParseHandling.None;
});
Run Code Online (Sandbox Code Playgroud)

但这没有用。

我尝试使用JsonConverter属性,但问题是在 ReadJson 重写方法上,读取器已经将字符串值解析为 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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*nta 1

最终找到了解决方法,由于此时无法访问 JsonSettings ,我正在使用 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;
       }        
   }
Run Code Online (Sandbox Code Playgroud)

通过这个简单的扩展:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)