2015-10-16 57 views
2

我檢索從WebRequest的一個JSON,我想反序列化到下面的類工作:DeserializeObject用的DateTime成員不Json.Net

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""}" 

據我可以告訴這個DateTime字符串是ISO 8601,但我不明白爲什麼有三個0末尾爲毫秒和一個額外的Z.這就是我想如何將字符串轉換爲我的對象:

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

這引發System.FormatException:String未被識別爲有效的DateTime。

當我嘗試添加的,而不是IsoDateTimeConverter這樣JsonSerializerSetting:

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

不會拋出異常,而是日期時間會員總是顯示01.01.0001 00:00:00

回答

5

問題是您的日期字符串格式不正確。在秒和毫秒之間應該有一個句點字符(.),而不是冒號(:)。 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

+0

謝謝你解決了這個問題。但是,我無法控制從服務器收到的內容,所以我想知道該字符串是錯誤的,還是我只是使用了錯誤的格式? – zlZimon

+0

該字符串錯誤。如果有期限,格式將是正確的;即ISO 8601格式,這是一個標準(「Z」代表祖魯時區,即UTC時間)。你可以聯繫API的提供者來讓他們解決它嗎?如果沒有,可能會創建一個JSON轉換器來嘗試修復反序列化期間的錯誤日期。 –

-1
var deserializeSetting = new JsonSerializerSettings() 
{ 
    DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("o") 
}; 

這應該工作,或嘗試Newtonsoft圖書館誰是真棒。

+0

我actualy使用json.Net Newtonsoft。我正在做的這些方法調用是Newtonsoft libriary調用。不幸的是在System.Runtime.Serialization中沒有DateTimeFormat。 – zlZimon

+0

有.NET 4.5及以上版本:https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datetimeformat(v=vs.110).aspx –

4
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 
     }; 
相關問題