使用Marvel API反序列化DateTime遇格式异常的解决方案咨询
问题核心
C# 的DateTime类型最小值为0001年1月1日,而Marvel API返回的-0001-11-30属于公元前日期,超出了DateTime的有效范围。哪怕将字段设为可空类型DateTime?,Json.NET在反序列化时仍会尝试解析这个无效日期,直接抛出异常,不会自动赋值为null。
解决思路
方法1:自定义Json转换器处理无效日期
编写自定义转换器,识别并过滤Marvel返回的特殊无效日期,解析失败时返回null。
示例转换器代码:
public class SafeNullableDateTimeConverter : JsonConverter<DateTime?> { public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value == null) return null; var dateStr = reader.Value.ToString(); // 匹配Marvel返回的无效日期 if (dateStr.Equals("-0001-11-30T00:00:00-0500", StringComparison.OrdinalIgnoreCase)) return null; if (DateTime.TryParse(dateStr, out var date)) return date; // 其他解析失败场景也返回null return null; } public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer) { if (value.HasValue) writer.WriteValue(value.Value.ToString("yyyy-MM-ddTHH:mm:sszzz")); else writer.WriteNull(); } }
在日期字段上标记使用该转换器(注意移除原有的[JsonIgnore]特性):
public class Comic { // ... 其他字段 [JsonConverter(typeof(SafeNullableDateTimeConverter))] public DateTime? Modified { get; set; } // ... 其他字段 } public class ComicDate { public string Type { get; set; } [JsonConverter(typeof(SafeNullableDateTimeConverter))] public DateTime? Date { get; set; } }
反序列化时直接调用:
var comicData = JsonConvert.DeserializeObject<ComicDataWrapper>(jsonContent);
方法2:先用字符串接收,再手动处理
将日期字段定义为字符串类型,反序列化完成后,通过额外属性手动转换或过滤无效值。
修改类定义:
public class Comic { // ... 其他字段 public string Modified { get; set; } // 只读属性:返回转换后的DateTime(无效日期返回null) public DateTime? ModifiedDate { get { if (string.IsNullOrEmpty(Modified) || Modified == "-0001-11-30T00:00:00-0500") return null; DateTime.TryParse(Modified, out var date); return date; } } // ... 其他字段 } public class ComicDate { public string Type { get; set; } public string Date { get; set; } public DateTime? ParsedDate { get { if (string.IsNullOrEmpty(Date) || Date == "-0001-11-30T00:00:00-0500") return null; DateTime.TryParse(Date, out var date); return date; } } }
方法3:使用DateTimeOffset类型接收
DateTimeOffset支持更广的日期范围(包括公元前年份),可以直接解析目标日期,之后按需转换为DateTime(注意:超出DateTime范围的日期转换时会抛异常,需加判断)。
修改字段类型:
public class Comic { // ... 其他字段 public DateTimeOffset? Modified { get; set; } // 可选:转换为DateTime的只读属性 public DateTime? ModifiedDateTime { get { if (!Modified.HasValue) return null; try { return Modified.Value.LocalDateTime; } catch { // 超出DateTime范围时返回null return null; } } } // ... 其他字段 } public class ComicDate { public string Type { get; set; } public DateTimeOffset? Date { get; set; } }
内容的提问来源于stack exchange,提问作者sesitosVDX
相关产品推荐
相关产品推荐

