如何防止单个对象属性在字符串时转换为DateTime

这是我必须使用的模型的简化版本:

class InputModel { public string Name { get; set; } public object Value { get; set; } } 

以及控制器的相关部分:

 class Controller : ApiController { [HttpPut] public async Task Update([FromBody]InputModel model) { //implementation } } 

InputModel类的Value属性可以是任何类型,它将在以后知道的类型中,在模型发送到的一段遗留代码中,我无法控制。

我在请求正文中使用以下json发生的问题:

 { "name": "X", "value": "2001-10-17T13:55:11.123" } 

默认行为是解析此json,以便将Value属性转换为DateTime。 但是,DateTimes的处理方式与遗留代码中的字符串截然不同,并且在处理后数据会丢失(例如:在持久保存到数据库时删除毫秒部分)。 因此,当稍后请求相同的值时,返回的值为“2001-10-17T13:55:11”(缺少毫秒)。

当然我可以通过在我的web api配置中全局设置来解决这个问题:

 httpConfiguration.Formatters.JsonFormatter.SerializationSettings.DateParseHandling = DateParseHandling.None; 

但这样做也会禁用解析DateTimes以用于其他方法和控制器中的模型,这些方法和控制器具有需要默认行为的模型。

我正在寻找的是类似下面的(想象的)代码:

 class InputModel { public string Name { get; set; } [JsonSerializerSettings(DateParseHandling = DateParseHandling.None)] public object Value { get; set; } } 

但我无法找到如何实现这一目标。 任何帮助将不胜感激。

可以做的是将自定义JsonConverter添加到InputModel类型以临时将InputModel切换为None

 [JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] class InputModel { public string Name { get; set; } public object Value { get; set; } } public class DateParseHandlingConverter : JsonConverter { readonly DateParseHandling dateParseHandling; public DateParseHandlingConverter(DateParseHandling dateParseHandling) { this.dateParseHandling = dateParseHandling; } public override bool CanConvert(Type objectType) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var old = reader.DateParseHandling; try { reader.DateParseHandling = dateParseHandling; existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator(); serializer.Populate(reader, existingValue); return existingValue; } finally { reader.DateParseHandling = old; } } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } 

请注意,如果要反序列化的JSON包含嵌套数组或对象,则所有递归包含的值都将使用DateParseHandling.None进行解析。

有人可能会问,为什么不直接在物业上添加转换器呢?

 class InputModel { public string Name { get; set; } [JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)] public object Value { get; set; } } 

事实certificate这不起作用,因为在调用JsonConverter.ReadJson() ,读者已经进入日期字符串并将其标记为DateTime 因此,转换器必须应用于包含类型。