Json.Net反序列化DateTimes不一致

rik*_*kit 5 c# datetime json date json.net

我无法deserialising日期时间与Json.Net 6.0.3(我可以复制在6.0.6的问题).代码在Windows 8.1上的.Net 4.5中运行,文化是en-GB.

这证明了这个问题:

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\"]");
Run Code Online (Sandbox Code Playgroud)

输出:

{
    "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"]
Run Code Online (Sandbox Code Playgroud)

日期时间根据JObject的访问方式而有所不同 - 一个是MM/DD/YYYY DD/MM/YYYY.为什么是这样?

我不需要它们采用特定格式:问题是格式改变了.我有很多遗留代码来解析源自Json.Net的日期时间字符串.该代码也将在世界各地的不同计算机上运行,​​可能具有不同的文化.

有没有办法让Json.Net始终以相同的格式返回日期时间?

And*_*ker 7

问题是两条线做了不同的事情:

jo["time"]
Run Code Online (Sandbox Code Playgroud)

是(最终)将实际DateTime值写入控制台.正如@JonSkeet指出的那样,你实际上正在JValue控制台写一个- JValue.ToString只是调用包装值的ToString方法,在你的情况下就是这样DateTime.ToString().

换一种说法:

  • 调用Console.WriteLine并传递一个JValue使用的实例的重载Console.WriteLine需要一个object.
  • 这超负荷电话.ToString()JValue
  • 然后调用.ToString()底层类型(在您的情况下为a DateTime)

因此,您将获得当前文化的默认格式.更具体地说,您将DateTime在当前文化中使用"G"说明符进行格式化.

jo.Value<string>("time")线路越有趣.在引擎盖下,JSON.NET DateTime使用以下内容将底层转换为字符串:

Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture);
Run Code Online (Sandbox Code Playgroud)

当然,这会产生完全不同的字符串,因为它是明确使用的CultureInfo.InvariantCulture.

从中得出的结论是,您最好的选择可能是将日期检索为a DateTime,然后按照您希望的方式对其进行格式化,以避免任何歧义:

DateTime dt = jo.Value<DateTime>("time");
string dateTimeSTring = dt.ToString(/* whatever format you always want */);
Run Code Online (Sandbox Code Playgroud)