【问题标题】:C# find JSON value based only on Key name through multiple levels of arrayC#通过多级数组仅根据键名查找JSON值
【发布时间】:2020-04-27 21:19:22
【问题描述】:

我有各种输入 JSON 格式的数据,它们都包含一个特定的键名 terminalSize。这是我知道的唯一一块。 JSON 树的总数或 JSON 树中 terminalSize 的确切深度将永远是未知数,并且可能会发生变化。

我正在寻找一种 C# 解决方案来循环遍历 JSON 字符串的每个子项并找到 terminalSize 然后获取值。

我已经成功地尝试过了,但它只有在 terminalSize 位于 JSON 的第一级时才有效:

var list = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(jsonString);
var dict = list.SelectMany(d => d).ToDictionary(p => p.Key, p => p.Value);
var terminal = dict["terminalSize"];

示例 1。

{
  "status": "success",
  "data": {
    "terminalSize": 3766505.46,
    "totalTerminalSize": 3766505.46
  },
  "message": null
}

示例 2。

{
  "lastUpdated": 1588020678,
  "terminalData": {
    "terminalSize": "451679852",
    "totalTerminalSize": "2100000000"
  },
  "terminalValueSeries": {
    "8x7": 2.33,
    "8x6": 3.73,
    "8x5": 4.49,
    "8x4": 3.68,
    "8x3": 13998,
    "8x2": 274936,
    "8x1": 5.09
  }
}

示例 3。

{
  "terminalSize": "492612346.17",
  "terminalStatus": "online"
}

【问题讨论】:

  • terminalSize 只出现一次吗?

标签: c# json linq json.net


【解决方案1】:

您还可以使用 linq 并根据 JProperty.Name 过滤 JProperty 集合。例如

var result = JObject.Parse(jsonString)
                    .DescendantsAndSelf()
                    .OfType<JProperty>()
                    .Single(x=>x.Name.Equals("terminalSize"))
                    .Value;

【讨论】:

    【解决方案2】:

    您可以将您的 JSON 解析为 JToken,然后使用 SelectToken 和递归下降 JsonPath 运算符 .. 在 JSON 中的任何位置获取 terminalSize

    var terminalSize = (double?) JToken.Parse(json).SelectToken("$..terminalSize");
    

    小提琴:https://dotnetfiddle.net/5ziYbP

    如果 JSON 中可能有多个 terminalSize 键,例如,如果您有一个终端数组,则可以改用 SelectTokens 并将终端大小放入由路径键入的 Dictionary 中:

    var sizes = JToken.Parse(json4)
                      .SelectTokens("$..terminalSize")
                      .ToDictionary(t => t.Path, t => (double)t);
    

    小提琴:https://dotnetfiddle.net/ivSM88

    【讨论】:

    • 感谢小提琴链接和工作示例。很有帮助!
    【解决方案3】:

    您可以将您的 JSON 解析为 JObject,然后递归地遍历所有属性和子对象以找到 terminalSize 值。无需将整个 JSON 反序列化为特定对象

    var json = JObject.Parse(jsonString);
    var result = GetTerminalSize(json);
    
    double GetTerminalSize(JObject input)
    {
        foreach (var property in input.Properties())
        {
            if (property.Name == "terminalSize")
                return property.Value.Value<double>();
    
            if (property.Value.Type == JTokenType.Object)
                return GetTerminalSize((JObject) property.Value);
    
            //not sure, if the is a need to handle an array
            if (property.Value.Type == JTokenType.Array)
                foreach (var item in (JArray) property.Value)
                    return GetTerminalSize((JObject) item);
        }
    
        return 0;
    }
    

    它为所有 3 个示例返回正确的值

    【讨论】:

    • 谢谢,很有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多