You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:39:52