当单个对象属性为字符串时,如何防止将其转换为 DateTime

2023-12-27

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

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。然而,日期时间的处理方式与遗留代码中的字符串非常不同,处理后数据会丢失(例如:在持久化到数据库时,毫秒部分被删除)。因此,当稍后请求相同的值时,返回的值为“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; }
}

但我不知道如何实现这一目标。任何帮助将不胜感激。


人们能做的就是添加一个custom JsonConverter http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm to the InputModel键入临时切换JsonReader.DateParseHandling http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonReader_DateParseHandling.htm to 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() http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_JsonConverter_ReadJson.htm被调用时,读者已经前进到日期字符串并将其标记为DateTime.因此转换器必须应用于包含类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当单个对象属性为字符串时,如何防止将其转换为 DateTime 的相关文章

随机推荐