如何在Web API的JObject中修正DateTime值后执行反序列化
处理Web API中格式错误的DateTime JSON字段
这问题我之前也碰到过,用户传的DateTime格式总是五花八门,尤其是这种带空格的"a. m."/"p. m.",确实挺头疼的。下面给你几个可行的实现方案,根据你的场景选就行:
方案一:先清洗原始JSON字符串(简单直接)
如果你的JSON结构不复杂,而且格式错误比较统一(比如只有"a. m."和"p. m."这两种错误),可以直接在反序列化前用正则替换掉错误的标识:
// 原始用户传入的JSON字符串 string rawJson = @"{ ""Pickedup"": 1, ""DATE"": ""05/24/2018 12:00:00 a. m."", ""TIME"": ""05/24/2018 06:24:00 AM"" }"; // 用正则匹配并替换不规范的上午/下午标识 string cleanedJson = Regex.Replace(rawJson, @"\ba\. m\.\b", "AM", RegexOptions.IgnoreCase); cleanedJson = Regex.Replace(cleanedJson, @"\bp\. m\.\b", "PM", RegexOptions.IgnoreCase); // 现在可以安全反序列化成你的实体类了 var yourModel = JsonConvert.DeserializeObject<YourModel>(cleanedJson);
优点:代码少,快速见效;缺点:如果JSON里其他非日期字段也有类似"a. m."的文本,可能会误替换(不过这种情况很少见)。
方案二:解析成JObject后精准修正字段(更安全)
如果你知道哪些字段可能出问题,可以先把JSON解析成JObject,然后针对性地修正指定字段的内容,避免误操作:
string rawJson = @"{ ""Pickedup"": 1, ""DATE"": ""05/24/2018 12:00:00 a. m."", ""TIME"": ""05/24/2018 06:24:00 AM"" }"; // 先解析成JObject JObject jObj = JObject.Parse(rawJson); // 定义一个通用的清洗方法,避免重复代码 string CleanDateTimeStr(string input) { return input.Replace("a. m.", "AM") .Replace("p. m.", "PM") .Trim(); } // 处理DATE字段 if (jObj["DATE"] is JValue dateVal && dateVal.Type == JTokenType.String) { jObj["DATE"] = CleanDateTimeStr(dateVal.Value<string>()); } // 处理TIME字段(如果需要的话) if (jObj["TIME"] is JValue timeVal && timeVal.Type == JTokenType.String) { jObj["TIME"] = CleanDateTimeStr(timeVal.Value<string>()); } // 反序列化成实体类 var yourModel = jObj.ToObject<YourModel>();
优点:只修改指定字段,不会影响其他内容;缺点:需要提前知道可能出问题的字段名,如果字段很多的话要写不少判断。
方案三:自定义JsonConverter(全局自动化处理)
如果你的API里很多DateTime字段都可能出现这种格式问题,最省心的方式是写一个自定义的JSON转换器,让反序列化过程自动处理格式修正:
public class FixedDateTimeConverter : JsonConverter<DateTime> { // 定义支持的日期格式,包括错误格式和正确格式 private readonly string[] _supportedFormats = new[] { "MM/dd/yyyy hh:mm:ss tt", "MM/dd/yyyy hh:mm:ss a. m.", "MM/dd/yyyy hh:mm:ss p. m." }; public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value is string dateStr) { // 先清洗格式错误的部分 string cleanedStr = dateStr.Replace("a. m.", "AM") .Replace("p. m.", "PM") .Trim(); // 尝试解析成DateTime if (DateTime.TryParseExact(cleanedStr, _supportedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)) { return result; } // 解析失败可以抛出业务异常,或者返回默认值(根据你的需求调整) throw new JsonSerializationException($"无法解析日期字符串:{dateStr}"); } throw new JsonSerializationException("日期字段必须是字符串类型"); } public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) { // 序列化时统一输出标准格式 writer.WriteValue(value.ToString("MM/dd/yyyy hh:mm:ss tt")); } }
使用的时候只需要在序列化配置里添加这个转换器:
var serializerSettings = new JsonSerializerSettings(); serializerSettings.Converters.Add(new FixedDateTimeConverter()); // 直接反序列化,转换器会自动处理格式问题 var yourModel = JsonConvert.DeserializeObject<YourModel>(rawJson, serializerSettings);
优点:一劳永逸,所有DateTime字段都会自动处理格式错误;缺点:需要额外写转换器类,适合长期维护的项目。
内容的提问来源于stack exchange,提问作者A.Goutam
相关产品推荐
相关产品推荐

