对文档反序列化禁用DateParseHandling



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

{
  "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#类将"CreatedOn"属性作为字符串

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

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

{
  "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重写方法上,读取器已经将字符串值解析为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
    }
}

关于如何克服这种自动解析,有什么想法吗?

JSON序列化程序设置现在可以直接传递给DocumentClient构造函数,这为您提供了所需的灵活性。

最终找到了一个解决方法,因为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;
       }        
   }

有了这个简单的扩展:

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

相关内容

  • 没有找到相关文章

最新更新