Получить абсолютный путь к объекту JSON - PullRequest
0 голосов
/ 23 октября 2019

У меня есть объект JSON:

{
  ""settings"": {
    ""general"": {
      ""database"": { ""type"": ""PostgreSql"" }
    }
  }
}

Абсолютный путь к моему объекту JSON будет выглядеть следующим образом: settings/general/database/type

Я попытался получить все ключи с помощью первого решенияэтого вопроса :

IList<string> keys = parent.Properties().Select(p => p.Name).ToList();

Это не сработало для меня. Список keys содержит только первый ключ settings и не имеет других ключей.

Существует свойство path, которое показывает путь к узлу, в котором вы находитесь, но не имеетпоказать полный путь к объекту JSON.

enter image description here

Как получить абсолютный путь, как в моем примере?

Ответы [ 3 ]

2 голосов
/ 23 октября 2019

В вашем вопросе вы спрашиваете, как получить путь к «моему объекту JSON», но ваш пример JSON на самом деле содержит четыре вложенных объекта. (Каждый объект начинается с { и заканчивается } в JSON.) Таким образом, путь будет отличаться в зависимости от того, на какой объект JSON вы ссылаетесь. Похоже, у вас есть ссылка на самый внешний объект, который вы запрашиваете, чтобы получить имена его свойств. Но это не даст вам свойства потомка, как вы видели. Вам нужно получить Path из внутреннего свойства.

Так что я думаю, что мы можем свести ваш вопрос к следующему:

Учитывая некоторый JSON, как мне получить полный путь к самым глубоким значениям в иерархии (т. Е. Конечные узлы)?

Вы можете сделать это с помощью этого LINQ-to-JSON запрос:

var obj = JObject.Parse(json);

var paths = obj.DescendantsAndSelf()
               .OfType<JProperty>()
               .Where(jp => jp.Value is JValue)
               .Select(jp => jp.Path)
               .ToList();

Если вам нужен только первый, замените .ToList() на .FirstOrDefault().

Обратите внимание, что путь(s) будут возвращены с точками в качестве разделителей. Если вы предпочитаете косую черту, то добавьте .Replace('.', '/') к jp.Path в вызове метода Select().

Рабочая демонстрация здесь: https://dotnetfiddle.net/lFXtEE

1 голос
/ 23 октября 2019

Ответ SO, на который вы ссылались, не работает, потому что он дает вам все ключи вашего корневого объекта в виде списка строк.

То, что вы хотите, - это рекурсивный способ получить все «ключи»(JProperty.Name). Если у вас есть JProperty с Name = "type", давайте назовем его JProperty typeProp;. Тогда typeProp.Parent даст вам JContainer, содержащий ""type"" : ""PostgreSql"", а typeProp.Parent.Parent даст вам JProperty с Name = "database".

Так что подобное может помочь (будьте осторожны, не проверено):

JToken current = typeProp;
string path = "";

while (current != null)
{
    path = current.Name + "/" + path;
    if(current.Parent != null) current = current.Parent.Parent;
}

Это даст вам дополнительную косую черту на конце, как это:

settings/general/database/type/

, которую вы можете удалить с помощью:

char[] charsToTrim = {'/'};
path.trimEnd(charsToTrim)
1 голос
/ 23 октября 2019

Ваш родительский объект имеет только один ключ, и это "настройки". Его значение является объектом json. Этот объект имеет только один ключ, и это «общий». Его значение является объектом json. Этот объект имеет только один ключ, и это «база данных». Его значение является объектом json. Вы используете вложенные объекты, поэтому вы должны быть конкретны в «желании всех ключей» какого объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...