Вопрос или проблема
Я работаю с 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 и делает код более читаемым и поддерживаемым. Советуем вам внедрить его в свою систему для повышения эффективности разработки.