使用日期时间成员反序列化对象不适用于 Json.Net



我正在从网络请求中检索一个JSON,我想将其反序列化为以下类:

public class MyData
{
   public int id { get; set; }
   public DateTime openTime { get; set; }
   MyData() {}
}

这是我从服务器收到的 JSON:

var json= @"{""Id"": ""12345"",""openTime"":""2015-09-01T12:00:00:000Z""}"

据我所知,这个日期时间字符串是ISO 8601,但我不明白为什么最后有三个0毫秒和一个额外的Z。这就是我尝试将字符串转换为我的对象的方式:

var responseInstance = JsonConvert.DeserializeObject<MyData>(json,new IsoDateTimeConverter());

这将引发 System.FormatException : 字符串未被识别为有效的日期时间。

当我尝试添加 JsonSerializerSetting 而不是像这样的 IsoDateTimeConverter 时:

var deserializeSetting = new JsonSerializerSettings()
{
   DateFormatHandling = DateFormatHandling.IsoDateFormat
};
var responseInstance = JsonConvert.DeserializeObject<MyData>(json,deserializeSetting);

不会引发异常,而是日期时间成员始终显示 01.01.0001 00:00:00

问题是您的日期字符串格式不正确。 秒和毫秒之间应该有一个句点字符(.(,而不是冒号(:(。 Json.Net 内部使用DateTime.Parse来解析日期。 如果失败,那么它会静默地吃掉错误,并且永远不会在您的对象上设置日期。 因此,您最终会得到默认日期 01/01/0001 00:00:00。

编辑

如果您无法更改 JSON(例如,因为它由第三方控制(,则可以使用自定义 JSON 转换器来允许正确反序列化错误的格式。

class BadDateFixingConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(DateTime) || objectType == typeof(DateTime?));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string rawDate = (string)reader.Value;
        DateTime date;
        // First try to parse the date string as is (in case it is correctly formatted)
        if (DateTime.TryParse(rawDate, out date))
        {
            return date;
        }
        // If not, see if the string matches the known bad format. 
        // If so, replace the ':' with '.' and reparse.
        if (rawDate.Length > 19 && rawDate[19] == ':')
        {
            rawDate = rawDate.Substring(0, 19) + '.' + rawDate.Substring(20);
            if (DateTime.TryParse(rawDate, out date))
            {
                return date;
            }
        }
        // It's not a date after all, so just return the default value
        if (objectType == typeof(DateTime?)) 
            return null;
        return DateTime.MinValue;
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

像这样使用它:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new BadDateFixingConverter() },
    DateParseHandling = DateParseHandling.None
};
MyData obj = JsonConvert.DeserializeObject<MyData>(json, settings);

小提琴:https://dotnetfiddle.net/M1w36e

class BadDateFixingConverter : JsonConverter
{
    string FormatStringVaue;
    public BadDateFixingConverter(string FormatString)
    {
        this.FormatStringVaue = FormatString;
    }
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(DateTime) || objectType == typeof(DateTime?));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string rawDate = (string)reader.Value;
        try
        {
            return DateTime.ParseExact(rawDate, FormatStringVaue, null);
        }
        catch
        {
            // It's not a date after all, so just return the default value
            if (objectType == typeof(DateTime?))
                return null;
            return DateTime.MinValue;
        }
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

像这样使用它:

       JsonSerializerSettings settings = new JsonSerializerSettings
        {
            Converters = new List<JsonConverter> {new BadDateFixingConverter("yyyyMMddHHmmss") },
            DateParseHandling = DateParseHandling.None
        };
var deserializeSetting = new JsonSerializerSettings()
{
    DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("o")
};

这应该有效,或者尝试牛顿软件图书馆,谁太棒了。

相关内容

  • 没有找到相关文章

最新更新