Как получить и установить вложенные данные в Newtonsoft.Json.JObject

Вопрос или проблема

Я работаю с C# и часто использую объекты Newtonsoft.Json, так как взаимодействую с клиентским Javascript и json.

Часто у меня есть сложная структура json, представляющая параметры чего-либо в классе C#. Я обычно оборачиваю большинство элементов в свойства C#, чтобы их было легче использовать из C# (и чтобы получить проверку типов на этапе компиляции).

Я хотел бы создать свойство, которое устанавливает multipage.pages в массив строк. Элемент ‘multipage’ может существовать или не существовать.

Мне интересно, предлагает ли Newtonsoft.Json простой способ обеспечить существование всех элементов в многослойном дереве при создании нового? Я пробовал

JObject j = new JObject();
j["multipage.keepSave"] = true;
Console.WriteLine(j.ToString());

но вывод был (что вполне понятно – json не имеет правил относительно того, что может быть в имени)

{
  "multipage,keepSave": true
}

Альтернативный подход кажется немного утомительным:

void Main() {
    Form f = new Form();
    Console.WriteLine(f.KeepSave);
    f.KeepSave = true;
    Console.WriteLine(f.KeepSave);
    f.KeepSave = false;
    Console.WriteLine(f.KeepSave);
    Console.WriteLine(f.Options.ToString());
}

public class Form {
    public JObject Options = new JObject();
    public bool KeepSave
    {
        get
        {
            JToken t = Options["multipage"];
            if(t == null)
                return false;
            return (bool)t["keepsave"]; 
        }
        set {
            JToken t = Options["multipage"];
            if(t == null)
                Options["multipage"] = t = new JObject();
            t["keepsave"] = value;
        }
    }
}

Предполагаю, что могу создать свой собственный обобщенный код:

void Main() {
    Form f = new Form();
    Console.WriteLine(f.KeepSave);
    f.KeepSave = true;
    Console.WriteLine(f.KeepSave);
    f.KeepSave = false;
    Console.WriteLine(f.KeepSave);
    Console.WriteLine(f.Options.ToString());
}

static public void SetJObject(JToken o, string path, object value) {
    List<string> p = path.Split('.').ToList();
    for(int i = 0; i < p.Count - 1; i++) {
    string name = p[i];
        JToken j = o[name];
        if(j == null)
            o[name] = j = new JObject();
        o = j;
    }
    o[p[p.Count - 1]] = JToken.FromObject(value);
}

public class Form {
    public JObject Options = new JObject();
    public bool KeepSave
    {
        get
        {
            JToken t = Options.SelectToken("multipage.keepsave");
            return t == null ? false : (bool)t; 
        }
        set {
            SetJObject(Options, "multipage.keepsave", value);
        }
    }
}

Предложения по улучшению приветствуются!

Ответ или решение

Для работы с вложенными данными в библиотеке Newtonsoft.Json при использовании C# есть несколько важных аспектов, на которые стоит обратить внимание. Данная библиотека предлагает удобные методы для работы с JSON-объектами, однако, когда дело касается вложенной структуры, такие операции могут потребовать определённой проработки.

Создание и установка вложенных данных в Newtonsoft.Json.JObject

Проблема

Ваша задача заключается в том, чтобы установить значение для свойства multipage.pages, которое может находиться не только на верхнем уровне, но также может быть вложенным. В случае, если элемент multipage ещё не существует, его необходимо создать.

Ваш исходный подход с использованием прямой установки значения через строку, как в следующем примере, работает некорректно:

JObject j = new JObject();
j["multipage.keepSave"] = true; // выводит "multipage,keepSave"

Это происходит из-за того, что JSON не поддерживает точечную нотацию в именах свойств.

Решение

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

Создание метода для установки значений

Метод SetJObject можно использовать для установки значения в указанном пути.

public static void SetJObject(JToken o, string path, object value)
{
    List<string> segments = path.Split('.').ToList();
    for (int i = 0; i < segments.Count - 1; i++)
    {
        string name = segments[i];
        JToken j = o[name];
        if (j == null)
            o[name] = j = new JObject();
        o = j;
    }
    o[segments.Last()] = JToken.FromObject(value);
}

Этот метод принимает объект JToken, строку пути и значение, которое необходимо установить. Он проходит по каждому сегменту пути, создавая необходимые объекты JObject, если они не существуют, и в конце устанавливает нужное значение.

Применение метода в классе

Теперь можно использовать этот метод в вашем классе. Например:

public class Form 
{
    public JObject Options = new JObject();

    public bool KeepSave
    {
        get 
        {
            JToken t = Options.SelectToken("multipage.keepSave");
            return t == null ? false : (bool)t; 
        }
        set 
        {
            SetJObject(Options, "multipage.keepSave", value);
        }
    }
}

Теперь вы можете установить значение свойства KeepSave, и оно корректно добавит всю необходимую иерархическую структуру JSON, если та ещё не была создана.

Пример использования

Теперь, когда всё настроено, вы можете использовать ваш класс следующим образом:

void Main() 
{
    Form f = new Form();
    Console.WriteLine(f.KeepSave); // false
    f.KeepSave = true;
    Console.WriteLine(f.KeepSave); // true
    f.KeepSave = false;
    Console.WriteLine(f.KeepSave); // false
    Console.WriteLine(f.Options.ToString()); // {"multipage": {"keepSave": false}}
}

Заключение

Используя данный подход, вы сможете с лёгкостью управлять вложенными данными в JSON-объектах с помощью Newtonsoft.Json. Это позволит вам не только избегать ошибок при работе с вложенными свойствами, но и поддерживать структуру данных в чистоте и порядке. Такой подход значительно упрощает работу с сложными структурами JSON и делает код более читаемым и поддерживаемым. Советуем вам внедрить его в свою систему для повышения эффективности разработки.

Оцените материал
Добавить комментарий

Капча загружается...