【问题标题】:Querying JSON using SelectTokens for a JSON object with a changing structure使用 SelectTokens 查询 JSON 以获取具有变化结构的 JSON 对象
【发布时间】:2018-01-03 00:13:12
【问题描述】:

这个问题和下面的问题很相关

Querying JSON with JSONPath or SelectTokens? With JSON.NET in C#

与上述问题类似,当 JSON 对象并不总是具有相同的简化数据结构时,我如何进行Where 查询,即

{
  "video": {
    "local_recording_device": {
      "codecs": null
    },
    "preferred_string": "___PREFERRED___",
    "streams": {
      "22855218": {
        "id": "22855218",
        "name": "AJA Camera"
      },
      "99176901": {
        "id": "99176901",
        "name": "PTZ Camera",
        "site": "someone",
        "email": "someone@awebsite.com",
        "codec": [
          "VP8",
          "HD1",
          "(720p)"
        ]
      },
      "3091494011": {
        "id": "3091494011",
        "name": "Logitech Webcam C930e",
        "site": "Joe Smith",
        "email": "joe@awebsite.com",
        "codec": [
          "VP8",
          "Medium",
          "(CIF)"
        ]
      },
      "3798287599": {
        "id": "3798287599",
        "name": "Drive Camera",
        "site": "ASiteName",
        "email": "asitesame@awebsite.com",
        "codec": [
          "HD1",
          "(720p)"
        ]
      }
    }
  }
}

如何让Where 查询在给定的编解码器上工作,例如“VP8”?

如果我这样查询它似乎不适用于我的应用程序:

string json = GetJson();
var obj = JObject.Parse(json);
var testcodec = "VP8";

var streamQuery = obj.SelectTokens("video.streams.*.codec")
                     .Where(s =>(string)s == testcodec);

但我的结果应该是这样的:

{  
  "video":{  
    "local_recording_device":{  
        "codecs":null
    },
    "preferred_string":"___PREFERRED___",
    "streams":{  
        "99176901":{  
            "id":"99176901",
            "name":"PTZ Camera",
            "site":"someone",
            "email":"someone@awebsite.com",
            "codec":[  
                "VP8"
            ]
        },
        "3091494011":{  
            "id":"3091494011",
            "name":"Logitech Webcam C930e",
            "site":"Joe Smith",
            "email":"joe@awebsite.com",
            "codec":[  
                "VP8"
            ]
        }
    }
  }
}

【问题讨论】:

  • 您期望得到什么以及实际得到什么?
  • 我想获得一个与原始结构相似但所有元素都满足我查询的数组。在这种情况下,完整的 json 树具有以下两个流 3091494011、99176901

标签: c# json json.net querying


【解决方案1】:

您的查询不起作用,因为它只要求编解码器数组,然后尝试将这些数组与字符串值进行比较。您需要一个询问流的查询,然后检查每个流的编解码器数组是否包含正确的字符串。

试试这样吧:

var streamQuery = obj.SelectTokens("video.streams.*")
                     .Where(t => t["codec"] != null &&
                                 t["codec"].Any(c => (string)c == testcodec));

然后你可以这样做从查询结果中获取数据:

foreach (var stream in streamQuery)
{
    Console.WriteLine("id: " + stream["id"]);
    Console.WriteLine("name: " + stream["name"]);
    Console.WriteLine("site: " + stream["site"]);
    Console.WriteLine("email: " + stream["email"]);
    Console.WriteLine("codecs: " + string.Join(", ", stream["codec"].Select(c => (string)c)));
    Console.WriteLine();
}

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

【讨论】:

  • 太棒了,快到了!!在我的编解码器列表中,我只想得到我正在寻找的单词,即在本例中为"codec":["VP8"]。你觉得这可能吗?
  • 你已经得到了它——它在你的testcodec变量中。您已经知道结果中的所有流都根据查询与此编解码器匹配。因此,对于每个结果,您只需执行 Console.WriteLine("codec: " + testcodec);
  • 谢谢,这有点太琐碎了。我已经更新了我的问题,非常感谢您的帮助!
  • 听起来您不仅要查询 JSON 并使用结果,而且要将 JSON 从一种形式转换到另一种形式——这就是我有听力吗?
  • 也许这就是我想要的术语。有没有一种简单的方法可以做到这一点?还是我必须遍历整个树并随时提取数据?非常感谢!!
【解决方案2】:
var streamQuery = obj.SelectTokens("$.video.streams.*.codec") .Where(x=>x.First.Value<string>()==testcodec);

【讨论】:

  • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
  • 现在obj.SelectTokens("$.video.streams.*.codec") 我得到一个空值
猜你喜欢
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多