Дсесериализация части объекта как subobject

169
12 марта 2022, 02:00

Допустим есть некий json объект, и мне не нравится расположение полей в нем:

{
    "title": "Игра престолов",
    "title_en": "Game of Thrones",
    "year": 2011,
    "tagline": "Победа или смерть",
    "description": "К концу подходит время благоденствия, и лето, длившееся почти десятилетие, угасает. Вокруг средоточия власти Семи королевств, Железного трона, зреет заговор, и в это непростое время король решает искать поддержки у друга юности Эддарда Старка. В мире, где все — от короля до наемника — рвутся к власти, плетут интриги и готовы вонзить нож в спину, есть место и благородству, состраданию и любви. Между тем, никто не замечает пробуждение тьмы из легенд далеко на Севере — и лишь Стена защищает живых к югу от нее.",
    "poster_url": "https://st.kp.yandex.net/images/film_iphone/iphone360_464963.jpg",
    "duration": 55,
    "countries": ["США", "Великобритания"],
    "genres": ["фэнтези", "боевик", "драма"],
    "kinopoisk_rating": 9,
    "kinopoisk_votes": 268732,
    "imdb_rating": 9.4,
    "imdb_votes": 1553335,
    "premiere_ru": "2011-09-08",
    "premiere_world": "2011-04-17",
    "actors": ["Питер Динклэйдж", "Лина Хиди", "Эмилия Кларк", "Кит Харингтон", "Софи Тёрнер", "Мэйси Уильямс", "Николай Костер-Вальдау", "Иэн Глен", "Алфи Аллен", "Джон Брэдли"],
    "directors": [ "Дэвид Наттер", "Алан Тейлор", "Алекс Грейвз"],
    "producers": ["Дэвид Бениофф", "Д.Б. Уайсс", "Джордж Р.Р. Мартин"],
    "writers": [ "Дэвид Бениофф", "Джордж Р.Р. Мартин", "Д.Б. Уайсс"],
    "composers": ["Рамин Джавади"],
    "editors": ["Кэти Вейланд", "Фрэнсис Паркер", "Криспин Грин"],
    "designers": ["Дебора Райли", "Джемма Джексон", "Филип Элтон"],
    "operators": ["Анетт Хаелльмигк", "Джонатан Фриман", "Роберт МакЛаклен"]
}

Мне не нравится то, что рейтинг, даты выхода и заголовки, находятся прямо в этом объекте, я хочу их вынести в отдельный интерфейс/класс.

Объявляю 3 подтипа интерфейсов:

// Заголовки
public interface ITitle
{
    string Russian { get; }
    string English { get; }
}
// Рейтинг
public interface IRating
{
    float Rating { get; }
    ulong VotesCount { get; }
}
// Премьеры
public interface IPremiere
{
    ref DateTimeOffset Russia { get; }
    ref DateTimeOffset World { get; }
}

В итоге получаю некий скомплектованный интерфейс:

public interface IData
{
    ITitle Title { get; }
    uint Year { get; }
    string Tagline { get; }
    string Description { get; }
    Uri PosterUri { get; }
    ushort Duration { get; }
    IRating KinopoiskRating { get; }
    IRating ImDbRating { get; }
    IPremiere Premiere { get; }
    IList<string> Countries { get; }
    IList<string> Genres { get; }
    IList<string> Actors { get; }
    IList<string> Directors { get; }
    IList<string> Producers { get; }
    IList<string> Writers { get; }
    IList<string> Composers { get; }
    IList<string> Editors { get; }
    IList<string> Designers { get; }
    IList<string> Operators { get; }
}

Вроде бы все не плохо, однако, мне теперь не понятно как мне сделать такой объект класса, что бы json десериализатор понял что куда класть.

Как можно решить такой вопрос?

Все что мне пришло на ум, это такая реализация:

internal class Data : IData
{
    #region Properties
    [JsonIgnore] public ITitle Title { get; }
    [JsonProperty("year")] public uint Year { get; }
    [JsonProperty("tagline")] public string Tagline { get; }
    [JsonProperty("description")] public string Description { get; }
    [JsonProperty("poser_url")] public Uri PosterUri { get; }
    [JsonProperty("duration")] public ushort Duration { get; }
    [JsonIgnore] public IRating KinopoiskRating { get; }
    [JsonIgnore] public IRating ImDbRating { get; }
    [JsonIgnore] public IPremiere Premiere { get; }
    [JsonProperty("countries")] public IList<string> Countries { get; }
    [JsonProperty("genres")] public IList<string> Genres { get; }
    [JsonProperty("actors")] public IList<string> Actors { get; }
    [JsonProperty("directors")] public IList<string> Directors { get; }
    [JsonProperty("producers")] public IList<string> Producers { get; }
    [JsonProperty("writers")] public IList<string> Writers { get; }
    [JsonProperty("composers")] public IList<string> Composers { get; }
    [JsonProperty("editors")] public IList<string> Editors { get; }
    [JsonProperty("designers")] public IList<string> Designers { get; }
    [JsonProperty("operators")] public IList<string> Operators { get; }
    #region SubObject data
    #region Title
    [JsonProperty("title")]
    internal string TitleRu
    {
        get { return Title.Russian; }
        set { ((Title) Title).Russian = value; }
    }
    [JsonProperty("title_en")]
    internal string TitleEn
    {
        get { return Title.English; }
        set { ((Title) Title).English = value; }
    }
    #endregion
    #region Rating
    [JsonProperty("kinipoisk_rating")]
    internal float KpRating
    {
        get { return KinopoiskRating.Value; }
        set { ((Rating) KinopoiskRating).Value = value; }
    }
    [JsonProperty("kinipoisk_rating")]
    internal ulong KpVotes
    {
        get { return KinopoiskRating.Votes; }
        set { ((Rating) KinopoiskRating).Votes = value; }
    }
    [JsonProperty("imdb_rating")]
    internal float ImdbRating
    {
        get { return ImDbRating.Value; }
        set { ((Rating) ImDbRating).Value = value; }
    }
    [JsonProperty("imdb_rating")]
    internal ulong ImdbVotes
    {
        get { return ImDbRating.Votes; }
        set { ((Rating) ImDbRating).Votes = value; }
    }
    #endregion
    #region Premiere
    [JsonProperty("premiere_ru")]
    internal DateTimeOffset PremiereRu
    {
        get { return Premiere.Russia; }
        set { Premiere.Russia = value; }
    }
    [JsonProperty("premiere_world")]
    internal DateTimeOffset PremiereWorld
    {
        get { return Premiere.World; }
        set { Premiere.World = value; }
    }
    #endregion
    #endregion
    #endregion
    internal MaterialData(uint year, string tagline, string description, Uri posterUri, ushort duration,
        IList<string> countries, IList<string> genres, IList<string> actors, IList<string> directors,
        IList<string> producers, IList<string> writers, IList<string> composers, IList<string> editors,
        IList<string> designers, IList<string> operators, DateTimeOffset premiereRu, DateTimeOffset premiereWorld,
        float kinopoiskRating, ulong kinopoiskVotes, float imdbRating, ulong imdbVotes)
    {
        Title = new Title();
        KinopoiskRating = new Rating();
        ImDbRating = new Rating();
        Premiere = new Premiere();
        Year = year;
        Tagline = tagline;
        Description = description;
        PosterUri = posterUri;
        Duration = duration;
        Countries = countries;
        Genres = genres;
        Actors = actors;
        Directors = directors;
        Producers = producers;
        Writers = writers;
        Composers = composers;
        Editors = editors;
        Designers = designers;
        Operators = operators;
        PremiereRu = premiereRu;
        PremiereWorld = premiereWorld;
        ImdbRating = imdbRating;
        ImdbVotes = imdbVotes;
        KpRating = kinopoiskRating;
        KpVotes = kinopoiskVotes;
    }
}
READ ALSO
Автозаполнение логина и пароля в приложении под iOS

Автозаполнение логина и пароля в приложении под iOS

Каким образом можно реализовать сохранение пароля в цепочке ключей, чтобы при входе в приложение на экране входа над клавиатурой показывалось...

149
Юнит-тестирование в геймдеве при наличии сильных зависимостей

Юнит-тестирование в геймдеве при наличии сильных зависимостей

Есть класс TextureRegion2D, который представляет собой прямоугольный фрагмент текстуры и принимает в конструкторе экземпляр Texture2D текстуры, на которой...

182
Получить все результаты из одного документа

Получить все результаты из одного документа

Народ делаю автокомплит, ищу по массиву тэгов в документе , как находится первый подходящий item из массива в результат выводится он , остальные...

67