以下是我必须使用的模型的简化版本:
class InputModel
{
public string Name { get; set; }
public object Value { get; set; }
}
控制器的相关部分:
class Controller : ApiController
{
[HttpPut]
public async Task<IHttpActionResult> Update([FromBody]InputModel model)
{
//implementation
}
}
InputModel类的Value属性可以是任何类型,以及它将在以后知道的类型,在模型发送到的一段遗留代码中,我无法控制。
我在请求正文中使用以下json发生了问题:
{
"name": "X",
"value": "2001-10-17T13:55:11.123"
}
默认行为是解析此json,以便将Value属性转换为DateTime。然而,DateTimes与遗留代码中的字符串的处理方式截然不同,并且在处理之后数据会丢失(例如:在持久化到数据库时删除毫秒部分)。因此,当稍后请求相同的值时,返回的值为&#34; 2001-10-17T13:55:11&#34; (缺少毫秒)。
当然,我可以通过在我的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; }
}
但我无法找到如何实现这一目标。任何帮助将不胜感激。
答案 0 :(得分:1)
可以做的是向InputModel
类型添加custom JsonConverter
以暂时将JsonReader.DateParseHandling
切换为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; }
}
事实证明这不起作用,因为在调用JsonConverter.ReadJson()
时,读者已经前进到日期字符串并将其标记为DateTime
。因此,必须将转换器应用于包含类型。