Страницы

Поиск по вопросам

суббота, 8 июня 2019 г.

Как использовать JSON5 в C#

Консольное приложение на С#
Со стороннего сайта получаю json в формате json5:
[{ contentId: 'f1654c004d0207fab3f1f30d9d5f7b1a', date: new Date('05/14/2018 10:50:00') }, { contentId: 'f1954d004d0287fab3f2f30d9d5f7b1a', date: new Date('08/24/2018 10:50:00') }, ... ]
Хранится в строковой переменной.
Вопрос в том какие варианты работы есть с таким существом в C#??
Что пробовал:
Подключить библиотеку JSON5 .NET. Не работает, не компилируется, написано что билд сломан Пройти регуляркой, остановился на проблеме полей с new Date: вот тут


Ответ

Вам может помочь Json.Net от Newtonsoft с кастомным конвертером даты.
Вообще, если гуглить does json.net support json5 мы сразу выходим на то, что поддержка ("большей части" - май 2017 года) уже есть. Но действительно, такие даты как у вас не поддерживаются.
Странный у вас вообще формат времени. Официальная спецификация json5 вообще ничего не говорит о формате времени, это оставлено на откуп спецификациям на Javascript:
JSON itself does not specify how dates should be represented, but JavaScript does. There is no right format; The JSON specification does not specify a format for exchanging dates which is why there are so many different ways to do it. The best format is arguably a date represented in ISO 8601 format (
(См. тут: The “right” JSON date format)
Но... у вас не ISO 8601 даты... у вас вообще в вопросе одни строки, а по ссылке с регуляркой другие (и подозреваю, что там правильно: формат MM/DD/YYYY HH:MM:SS).
В принципе, должно помочь написание кастомного конвертера, чего-то типа JavaScriptDateTimeConverter - вот например, очень похожий пример
Я не знаю, все ли даты приходят в таком формате, не знаю, насколько этот гос. сайт специфицирует такой формат (или может неожиданно перейти на ИСО 8601 - 2001 и поломать вам код), но в принципе, можно написать свой конвертер, обложить для надёжности юнит-тестами и тогда уже использовать в продакшене.
Вот вам рабочий приме для основы:
void Main() { var source = @"[ { contentId: 'f1654c004d0207fab3f1f30d9d5f7b1a', date: new Date('05/14/2018 10:50:00') }, { contentId: 'f1954d004d0287fab3f2f30d9d5f7b1a', date: new Date('05/14/2018 17:43:05') }]"; var parsed = Newtonsoft.Json.JsonConvert.DeserializeObject(source); parsed.Dump(); }
public class SomeClass { public string contentId { get; set; }
[JsonConverter(typeof(JavaScriptGovSiteDateTimeConverter))] public DateTime date { get; set; } }
public class JavaScriptGovSiteDateTimeConverter : JavaScriptDateTimeConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType); bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);
var token = JToken.Load(reader); if (token == null || token.Type == JTokenType.Null) { if (!isNullable) throw new JsonSerializationException(string.Format("Null value for type {0} at path {1}", objectType.Name, reader.Path)); return null; } if (token.Type != JTokenType.Constructor) { throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path)); } var constructor = (JConstructor)token; if (!string.Equals(constructor.Name, "Date", StringComparison.Ordinal)) { throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path)); }
var values = constructor.Values().ToArray();
if (values.Length == 0) { throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path)); } else if (values.Length == 1) { DateTime dt; if (!DateTime.TryParseExact(values[0].ToString(), "MM/dd/yyyy H:m:s", null, DateTimeStyles.None, out dt)) throw new Exception("date format is not MM/dd/yyyy H:m:s");
return dt; } else { throw new Exception("Вот сейчас прям совсем неожиданно было"); } } }

Комментариев нет:

Отправить комментарий