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

224
28 мая 2018, 05:10

Консольное приложение на С#

Со стороннего сайта получаю 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#??

Что пробовал:

  1. Подключить библиотеку JSON5 .NET. Не работает, не компилируется, написано что билд сломан
  2. Пройти регуляркой, остановился на проблеме полей с new Date: вот тут
Answer 1

Вам может помочь 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<SomeClass[]>(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("Вот сейчас прям совсем неожиданно было");    
        }
    }
}

READ ALSO
Внутренний оптимизатор Mysql

Внутренний оптимизатор Mysql

Слышал про существование внутреннего оптимизатора в mysql, в доках ничего такого не нашел

221
Как заполнить foreign key mysql

Как заполнить foreign key mysql

у меня есть таблица Form(по типу чека) связаная с таблицами Book,Worker,Reader, нужно заполнить foreign key(idBook,idWorker,idReader) в таблице Form, столбец kod думал сделать,как...

208
Как реализовать if foreach

Как реализовать if foreach

Как сделать так: если в бд столбец = 1, то foreach я пытался так,

219
Некорректная запись данных из Option в БД

Некорректная запись данных из Option в БД

Стоит задача сделать запись настроек из формы, где в option человек будет указывать модель:

201