У меня фактически была та же самая проблема ранее сегодня, я не мог сначала найти этот вопрос на SO, и в итоге я написал свой собственный метод расширения, который возвращает объекты JValue
, содержащие значения листовых узлов BLOB-объекта JSON. Это похоже на принятый ответ, за исключением некоторых улучшений:
- Он обрабатывает любой JSON, который вы ему даете (массивы, свойства и т. Д.), А не просто объект JSON.
- Меньше использования памяти
- Нет вызовов на
.Count()
для потомков, которые вам в конечном итоге не нужны
В зависимости от вашего варианта использования, они могут или не могут иметь значение, но они для моего случая. Я написал об обучении выравниванию объектов JSON.NET в моем блоге . Вот метод расширения, который я написал:
public static class JExtensions
{
public static IEnumerable<JValue> GetLeafValues(this JToken jToken)
{
if (jToken is JValue jValue)
{
yield return jValue;
}
else if (jToken is JArray jArray)
{
foreach (var result in GetLeafValuesFromJArray(jArray))
{
yield return result;
}
}
else if (jToken is JProperty jProperty)
{
foreach (var result in GetLeafValuesFromJProperty(jProperty))
{
yield return result;
}
}
else if (jToken is JObject jObject)
{
foreach (var result in GetLeafValuesFromJObject(jObject))
{
yield return result;
}
}
}
#region Private helpers
static IEnumerable<JValue> GetLeafValuesFromJArray(JArray jArray)
{
for (var i = 0; i < jArray.Count; i++)
{
foreach (var result in GetLeafValues(jArray[i]))
{
yield return result;
}
}
}
static IEnumerable<JValue> GetLeafValuesFromJProperty(JProperty jProperty)
{
foreach (var result in GetLeafValues(jProperty.Value))
{
yield return result;
}
}
static IEnumerable<JValue> GetLeafValuesFromJObject(JObject jObject)
{
foreach (var jToken in jObject.Children())
{
foreach (var result in GetLeafValues(jToken))
{
yield return result;
}
}
}
#endregion
}
Затем в своем коде вызова я просто извлекаю свойства Path
и Value
из возвращенных объектов JValue
:
var jToken = JToken.Parse("blah blah json here");
foreach (var jValue in jToken.GetLeafValues())
{
Console.WriteLine("{0} = {1}", jValue.Path, jValue.Value);
}