Json.Net deserializing DateTimes inconsistently

I am having trouble deserializing datetimes with Json.Net 6.0.3 (I can reproduce the problem in version 6.0.6). The code runs in .Net 4.5 on Windows 8.1, and the culture is en-GB.

This demonstrates the problem:

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\"]"); 

conclusion:

 { "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"] 

Date time varies depending on how you access the JObject - one of them is MM / DD / YYYY DD / MM / YYYY. Why is this?

I do not need them in a specific format: the problem is that the format is changing. I have a lot of legacy code that parses a datetime string derived from Json.Net. The code will also run on different computers around the world, possibly with different cultures.

Is there a way to force Json.Net to always return datetime in the same format?

+5
source share
1 answer

The problem is that the two lines have different things:

 jo["time"] 

Is (ultimately) writing the actual DateTime value to the console. Since @JonSkeet points to , you are actually writing JValue on the console - JValue.ToString just calls the completed value ToString method, though , which in your case is DateTime.ToString() .

In other words:

  • Calling Console.WriteLine and passing an instance of JValue uses the Console.WriteLine overload, which takes an object .
  • Overloading .ToString() calls .ToString() JValue
  • which then calls .ToString() in the base type (in your case a DateTime )

So, you will get some default format for your current culture. More specifically, you are going to get a "G" DateTime in your current culture.

A more interesting bit is the string jo.Value<string>("time") . Under the hood , JSON.NET converts the underlying DateTime to a string using the following:

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

This, of course, creates a completely different line, since it explicitly uses CultureInfo.InvariantCulture .

The conclusion from this is that the best choice is probably to get the date as a DateTime , and then format it exactly the way you want to avoid any ambiguity:

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

Source: https://habr.com/ru/post/1209373/


All Articles