我在使用 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 始终以相同的格式返回日期时间?
问题是这两行做不同的事情:
jo["time"]
(最终(将实际DateTime
值写入控制台。正如@JonSkeet指出的那样,您实际上是在向控制台写入JValue
- JValue.ToString
只是调用包装值的ToString
方法,在您的情况下是DateTime.ToString()
。
换句话说:
- 调用
Console.WriteLine
并传递JValue
实例会使用占用object
的Console.WriteLine
重载。 - 这种重载调用
.ToString()
JValue
- 然后调用基础类型的
.ToString()
(在您的情况下为DateTime
(
因此,您将获得当前文化的默认格式。更具体地说,您将在当前区域性中使用"G"说明符格式化DateTime
。
更有趣的一点是jo.Value<string>("time")
线。在后台,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 */);