在文档反序列化时禁用 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,这允许您需要的灵活性。
我们在 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,这允许您需要的灵活性。