Правильная сериализация

158
31 октября 2019, 07:40

Познаю науку JSON в C#. Действую по статьям и мануалам. Поставил цель разбивать текст, на определенный JSON. Для того, чтобы редактировать новость на сайте не вглядываясь каждый раз в JSON. И так есть такой JSON:

{
  "feed": {
    "feedBoxes": [
      {
        "$type": "newsBox",
        "title": "Заголовок",
        "id": "top_news",
        "content": [
          {
            "$type": "Paragraph",
            "content": [
              {
                "$type": "Text",
                "value": "Первый абзац"
              }
            ]
          },
          {
            "$type": "Paragraph",
            "content": [
              {
                "$type": "Text",
                "value": "Первый абзац"
              }
            ]
          }
        ]
      }
    ]
  }
}

Подключил Newtonsoft.Json, начал серелизовать ,но в один момент упёрся в это: Мой код класс для сереализации:

    public partial class FeedNews
    {
        [JsonProperty("feed")]
        public Feed Feed { get; set; }
    }
    public partial class Feed
    {
        [JsonProperty("feedBox")]
        public List<FeedBox> FeedBoxes { get; set; }
    }
    public partial class FeedBox
    {
        [JsonProperty("$type")]
        public string Type { get; set; }
        [JsonProperty("title")]
        public string Title { get; set; }
        [JsonProperty("id")]
        public string Id { get; set; }
        [JsonProperty("content")]
        public List<FeedBoxContent> Content { get; set; }
    }
    public partial class FeedBoxContent
    {
        [JsonProperty("$type")]
        public string Type { get; set; }
        [JsonProperty("content")]
        public List<ContentContent> Content { get; set; }
    }
    public partial class ContentContent
    {
        [JsonProperty("$type")]
        public string Type { get; set; }
        [JsonProperty("value")]
        public string Value { get; set; }
    }

Вот так начинаю разбивать текст:

    FeedNews feed = new FeedNews
    {
        Feed = new Feed
        {
            FeedBoxes = new List<FeedBox>
            {
            }
        }
    };

И вот на этом моменте всё получается:

{
  "feed": {
    "feedBoxes": []
  }
}

А дальше не понимаю как задать значения полей. Думал, что:

FeedNews feed = new FeedNews
{
    Feed = new Feed
    {
        FeedBoxes = new FeedBox<FeedBox>
        {
                    Title = "123",
                    Type = "123",
                    Id = "123",
                    Content = new FeedBoxContent
                    {
                        Type = "text",
                        Content = "content"
                    }
        }
    }
};

Помогите, объясните, как правильно вкладывть данный в такие запросы.

Answer 1

По сути тут нечего сложного нету, главное понимать какой тип используется.
Давайте пройдемся по порядку:

  • "feed": {} - это простой объект с названием feed.
  • "feedBoxes": [] - это массив объектов с названием feedBoxes.
  • "title": "Заголовок" - свойство, название которого title, а значение "Заголовок".
    Тут надо понимать также тип. Если это текст, то string, число - int и т.д.

Теперь давайте составим всю структуру с нуля:

  1. Создадим для удобства базовый класс, я назову его Root, в нем сделаем свойство класса Feed, которое для удобства сразу инициализируем. Получаем что то вроде:

    class Root
    {
        public Feed Feed { get; set; } = new Feed();
    }
  2. Далее сам класс Feed, он содержит в себе массив feedBoxes, для удобной работы пусть это будет свойство с типом List<FeedBox>, ну и также инициализируем сразу:

    class Feed
    {
        public List<FeedBox> FeedBoxes { get; set; } = new List<FeedBox>();
    }
  3. Каждый элемент FeedBox содержит в себе ряд свойств и массив content. Для удобного заполнения мы создадим еще конструктор, который будет принимать необходимые нам значения:

    class FeedBox
    {
        public FeedBox(string type, string title, string id)
        {
            Type = type;
            Title = title;
            Id = id;
        }
        [JsonProperty("$type")] public string Type { get; set; }
        public string Title { get; set; }
        public string Id { get; set; }
        [JsonProperty("Content")]
        public List<ContentMain> Contents { get; set; } = new List<ContentMain>();
    }
  4. Остается сам Content и его "основной класс. В нем у нас всего два свойства, ну и конструктор:

    class Content
    {
        public Content(string type, string value)
        {
            Type = type;
            Value = value;
        }
        [JsonProperty("$type")] public string Type { get; set; }
        public string Value { get; set; }
    }

    ну и

    class ContentMain
    {
        public ContentMain(string type)
        {
            Type = type;
        }
        [JsonProperty("$type")] public string Type { get; set; }
        [JsonProperty("Content")]
        public List<Content> Contents { get; set; } = new List<Content>();
    }
  5. Ну что, структуру мы сделали, давайте заполним:

    var root = new Root();
    var feetBox = new FeedBox("newsBox", "Заголовок", "top_news");
    var firstContent = new ContentMain("Paragraph");
    firstContent.Contents.Add(new Content("Text", "Первый абзац"));
    feetBox.Contents.Add(firstContent);
    var secondContent = new ContentMain("Paragraph");
    secondContent.Contents.Add(new Content("Text", "Первый абзац"));
    feetBox.Contents.Add(secondContent);
    root.Feed.FeedBoxes.Add(feetBox);
  6. Все, осталось сериализировать. Я добавлю пару настроек сериализации для того, что бы все значения были в нижнем регистре и JSON формировался не в одну строку:

    var serializerSettings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        Formatting = Formatting.Indented
    };
    var json = JsonConvert.SerializeObject(root, serializerSettings);

Все, видим следующий результат:

{
  "feed": {
    "feedBoxes": [
      {
        "$type": "newsBox",
        "title": "Заголовок",
        "id": "top_news",
        "content": [
          {
            "$type": "Paragraph",
            "content": [
              {
                "$type": "Text",
                "value": "Первый абзац"
              }
            ]
          },
          {
            "$type": "Paragraph",
            "content": [
              {
                "$type": "Text",
                "value": "Первый абзац"
              }
            ]
          }
        ]
      }
    ]
  }
}

Как видите все очень легко, простая работа с классами.

Answer 2

Ваша ошибка в том, что вы пытаетесь заполнить поля FeedBoxes и Content объектами, а нужно списками объектов.

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

FeedNews feed = new FeedNews
{
    Feed = new Feed
    {
        FeedBoxes = new List<FeedBox>
        {
            new FeedBox
            {
                Title = "123",
                Type = "123",
                Id = "123",
                Content = new List<FeedBoxContent>
                {
                    new FeedBoxContent
                    {
                        Type = "Paragraph",
                        Content = new List<ContentContent>
                        {
                            new ContentContent
                            { 
                                Type = "Text", 
                                Value = "Первый абзац" 
                            }
                        }
                    },
                    new FeedBoxContent
                    {
                        Type = "Paragraph",
                        Content = new List<ContentContent>
                        {
                            new ContentContent
                            { 
                                Type = "Text", 
                                Value = "Первый абзац" 
                            }
                        }
                    }
                } 
            }        
        } 
    }
};
READ ALSO
Активная вкладка браузера Selenium

Активная вкладка браузера Selenium

В моей программе у пользователя может быть открыто множество вкладок и мне надо понимать в какой он сейчас (активной) при условии что он сам...

151
Жидкость в Unity [закрыт]

Жидкость в Unity [закрыт]

Как можно сделать подобие воды или лавы в Unity?

124
Счетчик запущенных Task

Счетчик запущенных Task

В своем приложении использую много фоновых задач

118
NAudio - Mp3FileReader - медленный вывод аудио

NAudio - Mp3FileReader - медленный вывод аудио

Я преобразую входящий поток wav в mp3 через Lame этой функцией:

149