Json.Net反序列化DateTimes不一致

时间:2014-12-17 15:58:34

标签: c# json date datetime json.net

我无法使用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\"]");

输出:

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

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

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

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

1 个答案:

答案 0 :(得分:7)

问题是这两行做了不同的事情:

jo["time"]

是(最终)向控制台写入实际的DateTime值。作为@JonSkeet points out,您实际上正在向控制台JValue.ToString just calls the wrapped value's ToString method thoughJValue,在您的情况下为DateTime.ToString()

换句话说:

  • 调用Console.WriteLine并传递JValue的实例会使用Console.WriteLine的重载object
  • 该重载在.ToString()
  • 上调用JValue
  • 然后在底层类型上调用.ToString()(在您的情况下为DateTime

因此,您将获得当前文化的默认格式。更具体地说,您将使用&#34; G&#34;格式化DateTime格式。当前文化中的说明者。

更有趣的是jo.Value<string>("time")行。 Under the hood,JSON.NET使用以下内容将基础DateTime转换为字符串:

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

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

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

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