2014-12-17 9 views
5

Json.Net 6.0.3 ile zaman zaman hata ayıklamada sorun yaşıyorum (sorunu 6.0.6'da çoğaltabilirim). Kod, Windows 8.1'de .Net 4.5'te çalıştırılır ve kültür en-GB'tır. Json.Net deserialising DateTimes tutarsız bir şekilde

Bu

sorunu göstermektedir:

using Newtonsoft.Json; 
using Newtonsoft.Json.Linq; 

var d1 = new DateTimeOffset(2014, 12, 15, 18, 0, 0, TimeSpan.FromHours(1)); 
var obj = new { 
    time = d1 
}; 

var json = JsonConvert.SerializeObject(obj, Formatting.Indented); 
Console.WriteLine(json); 

var jo = JObject.Parse(json); 

Console.WriteLine(jo.Value<string>("time") + " // jo.Value<string>(\"time\")"); 
Console.WriteLine(jo["time"] + " // jo[\"time\"]"); 

çıkışı:

{ 
    "time": "2014-12-15T18:00:00+01:00" 
} 
12/15/2014 17:00:00 // jo.Value<string>("time") 
15/12/2014 17:00:00 // jo["time"] 

tarih kez JObject erişilir nasıl bağlı olarak farklılık gösterir - biridir AA/GG/YYYY GG/AA/YYYY. Bu neden?

Belirli bir biçimde olması için onlara ihtiyacım yok: Sorun, biçimin değişmesidir. Json.Net kaynaklı datetime dizesini ayrıştıran bir sürü eski kodum var. Kod ayrıca dünyadaki farklı bilgisayarlarda, belki farklı kültürlerde çalışacaktır.

Json.Net'in her zaman datetimes'leri her zaman aynı biçimde döndürmesini sağlamanın bir yolu var mı?

jo["time"] 

mi (sonuçta) konsola gerçek DateTime değerini yazma:

cevap

7

konu iki satır farklı şeyler yapmak olmasıdır. @JonSkeet points out olarak, aslındanumaralı JValue konsoluna - JValue.ToString just calls the wrapped value's ToString method though yazıyorsunuz. Başka bir deyişle

:

  • Console.WriteLine çağrılması ve JValue bir örneğini geçen bir object alır Console.WriteLine aşırı yüklenmesini kullanır. Daha sonra altta yatan türüne .ToString() çağırır JValue
  • üzerinde Çağrıları .ToString() aşırı
  • (sizin durumunuzda bir DateTime)

Yani geçerli kültürün varsayılan neyse biçim almaya gidiyoruz . Daha spesifik olarak, mevcut kültürünüzdeki "G" belirteci ile biçimlendirilmiş DateTime elde edersiniz.

Daha ilginç olan bit jo.Value<string>("time") satırdır. Under the hood, JSON.NET aşağıdaki kullanarak bir dizeye yatan DateTime dönüştürmektedir: açıkça CultureInfo.InvariantCulture kullanıyor beri

Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture); 

Bu, elbette, tamamen farklı dize üretir.

bu en iyi bahis Oluşabilecek karışıklıkları önlemek için DateTime olarak tarih alır ve ardından, o bunu tam olarak istediğiniz şekilde biçimlendirmek için muhtemelen olmasıdır gelen paket:

DateTime dt = jo.Value<DateTime>("time"); 
string dateTimeSTring = dt.ToString(/* whatever format you always want */); 
+0

Eh, ilk satırı konsola bir “JValue” yazıyor ... –

+0

@JonSkeet: Evet, fazla basitleştirdim, fakat 'JValue' 'ToString' yöntemi temel değerin (bu durumda bir 'DateTime') çağrısını yapıyor. ToString' yöntemi. –

+1

Sağ. Senin yerinde olsaydım, onu aşırı basitleştirirdim. Temel dayanak iyidir (bu yüzden kendi cevabımı terk ettim), ancak dönüşümler her yerdeyken bu konuda kesin olmak iyidir. –