Json.Net deserializing DateTimes непоследовательно
У меня возникли проблемы с десериализацией datetimes с Json.Net 6.0.3 (я могу воспроизвести проблему в версии 6.0.6). Код запускается в .Net 4.5 в Windows 8.1, а культура - 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. Почему это?
Мне не нужны они в определенном формате: проблема в том, что формат меняется. У меня много устаревшего кода, который анализирует строку datetime, полученную из Json.Net. Код также будет работать на разных компьютерах по всему миру, возможно, с разными культурами.
Есть ли способ заставить Json.Net всегда возвращать datetime в том же формате?
Проблема в том, что две строки имеют разные вещи:
jo["time"]
Является (в конечном счете) записывает фактическое значение 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);
Это, конечно, создает совершенно другую строку, так как она явно использует CultureInfo.InvariantCulture
.
Вывод из этого состоит в том, что лучший выбор - это, вероятно, получить дату как DateTime
, а затем отформатировать ее точно так, как вы хотите, чтобы избежать какой-либо двусмысленности:
DateTime dt = jo.Value<DateTime>("time");
string dateTimeSTring = dt.ToString(/* whatever format you always want */);