0

Не могу понять как десерилиазовать json ответ от сервера, в котором возращается массив объектов в каждом из которых поле имеет разное имя.

{
   "status":1,
   "msg":"ok",
   "data":[
      {
         "2020-08-21":4
      },
      {
         "2020-08-22":1
      },
      {
         "2020-08-24":1
      }
   ]
}

Подскажите, пожалуйста, как можно реализовать десерелизацию. Использую библиотеку Newtonsoft.Json

motpfofs
  • 1,274
  • 2
  • 10
  • 24
  • Вы точно не нашли ни одного примера десереализации json с помощью самой популярной библиотеки в .NET? Если же нашли, попытались, и не получилось, добавьте код вашей попытки в вопрос. И расскажите, в чем именно проблема. – aepot Aug 21 '20 at 09:54
  • @aepot, У меня вызывает трудность распарсить именно массив "data", т.к. поля динамичны, а классы для парсинга статичны, над этим ломаю голову, не знаю как распарсить – FERROUS SAGE Aug 21 '20 at 10:18
  • Когда встречаются объекты с динамически задаваемыми имён свойств, можно использовать словарь для их десериализации. В частности, List<Dictionary<string, int>> Data - такое свойство успешно подойдёт. – Alexander Petrov Aug 21 '20 at 11:48
  • 1
    А все потому, что data у вас походу словарь. Попробуйте в своем классе его обозначить как Dictionary<string, int> – tym32167 Aug 21 '20 at 11:48
  • Спасибо Вам за ответы, да, это работает) – FERROUS SAGE Aug 21 '20 at 11:52

1 Answers1

0

Попробуйте воспользоваться этим кодом:

public static void Main()
{
    var jsonString = @"{""status"":1,""msg"":""ok"",""data"":[{""2020-08-21"":4},{""2020-08-22"":1},{""2020-08-24"":1}]}";
    var deserializedResult = JsonConvert.DeserializeObject<JsonObject>(jsonString);
}
public class JsonObject
{
    public int Status { get; set; }
public string Msg { get; set; }

[JsonConverter(typeof(MyDateTimeConverter))]
public MyDateTime[] Data { get; set; }

}

public class MyDateTime
{
    public DateTime Date { get; set; }

    public int Value { get; set; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var result = new List<MyDateTime>();

    if (reader.TokenType == JsonToken.StartObject)
    {
        var instance = serializer.Deserialize<JObject>(reader);

        foreach (JProperty property in instance.Properties())
        {
            result.Add(new MyDateTime
            {
                Value = property.Value.ToObject<int>(),
                Date = DateTime.Parse(property.Name)
            });
        }
    }
    else if (reader.TokenType == JsonToken.StartArray)
    {
        var myDateTimes = serializer.Deserialize<JArray>(reader);

        foreach (var myDateTime in myDateTimes)
        {
            foreach (JProperty property in ((JObject)myDateTime).Properties())
            {
                result.Add(new MyDateTime
                {
                    Value = property.Value.ToObject<int>(),
                    Date = DateTime.Parse(property.Name)
                });
            }
        }
    }

    return result.ToArray();
}

результат

motpfofs
  • 1,274
  • 2
  • 10
  • 24
  • Спасибо за ответ! К сожалению, я получаю вот такой эксешпен - "Не удалось привести тип объекта "Newtonsoft.Json.Linq.JObject" к типу "Newtonsoft.Json.Linq.JArray"."

    Скажите, пожалуйста, как использовать приведенный Вами пример кода?

    – FERROUS SAGE Aug 21 '20 at 10:17
  • скажите, пожалуйста, как можно использовать этот код, когда может поле data не быть массивом, а просто строкой. Допустим, исполнения по дате были только в один день(т.е. проверяю исполнения на сегодняшний день), в таком случае поле data будет не массивом

    именно по этой причине я получал эксепшен, что описал выше

    – FERROUS SAGE Aug 21 '20 at 10:38
  • то есть выглядит в таком случае json строка вот так - var jsonString = @"{""status"":1,""msg"":""ok"",""data"":""2020-08-21"":4}"; – FERROUS SAGE Aug 21 '20 at 10:43
  • 1
    Такая строка не является валидным JSON из за отсутствия { } или [ ] в ""data"":""2020-08-21"":4 Честно говоря, не представляю как с ней справиться. – motpfofs Aug 21 '20 at 10:54
  • Извините, я ошибся немного со строкой. Она выглядит вот в таком виде - {"status":1,"msg":"ok","data":{"2020-08-21":4}}. В случае, если дат больше одной, то поле data будет массивом – FERROUS SAGE Aug 21 '20 at 11:03
  • Как вариант создать два класса, один с массивом, другой без и заполнять их по условию наличия [`] – Ivan Aug 21 '20 at 11:09
  • @FERROUSSAGE , я обновил код, посмотрите, пожалуйста. Добавленна проверка на то, что из себя представляет поле: объект или массив. Должно работать. – motpfofs Aug 21 '20 at 11:36
  • @motpfofs, Спасибо Вам большое, работает) – FERROUS SAGE Aug 21 '20 at 11:51