用Linq查询复杂的Json

时间:2014-03-26 20:34:16

标签: c# json linq json.net

我想在json字符串中创建一个Linq查询。

关于我想要做什么的一点信息。在工作中,我们有一个基于网络的日程安排系统,它不支持Windows 8和Windows Phone 8应用程序。这就是为什么我决定制作一个。使用HttpClient我得到一个http字符串,然后我转换为xml然后转换为Json。 正如您可以从(下面的链接,TheWholeJsonString.json'文件)中看到的那样,属性名称和JSON对象名称不提供信息且JSON文件很复杂。这就是为什么我决定从JSON字符串中提取一些值并编写一个全新的JSON文件,其中包含提取的JSON值,以更加丰富的方式。

原始JSON文件中的[tr]数组有几个JSON对象。在' VeryShorten.json'里面在链接文件夹中你可以看到其中一个对象的结构(OBS!有不同结构的objcet)。我隐藏的唯一东西是RL ppl的名称和电子邮件地址。

我还附上了' ShortenVersion.json'这只是整个json字符串的缩短版本,只是为了使它易于处理。

Json data sample

{
    "@class": "odd",
    "td": [
      {
        "@class": "user",
        "@onmouseover": "userInfo('149');",
        "@onmouseout": "userInfo(0);",
        "@onmousemove": "moveSlotInfo();",
        "#text": " ",
        "a": {
          "@href": "Name3@dreamnet.com",
          "#text": "Name3"
        }
      },
      .
      .
      .

在C#中如果我尝试以下代码(不是Linq)

var jObject = JObject.Parse(jString); //jString is 'TheWholeJsonString.json' file in the attached link

var jObj = jObject["tbody"]["tr"][8];
var gh = jObj.Value<JToken>("td").Children().First().Value<JToken>("a").Value<string>("#text");

我可以获得&#39; #text&#39;的价值这是*&#39; Name3&#39;。

但是,如果我尝试以下代码(Linq版本): -

var jObject = JObject.Parse(jString);
var jCollection = jObject["tbody"]["tr"].Children();
var test = from userToken in jCollection
            where
                userToken.Value<JToken>("td")
                    .Children()
                    .First()
                    .Value<JToken>("a")
                    .Value<string>("#text")
                    .Contains("Name3")
            select (string)userToken["#text"];
foreach (var item in test)
{
   var fgh = item.Type;
}

它将在foreach循环的第一次迭代中断开,并显示以下错误消息&#34;无法在Newtonsoft.Json.Linq.JValue&#34;上访问子值。我现在真的是导致问题的原因,但我不知道如何解决它。问题是并非jCollection中的每个令牌都有一个&#39; td&#39;对象,即使令牌有&#39; td&#39;对象并非总是它有令牌&#39; a&#39;。您可以在&#39; TheWholeJsonString.json&#39;中看到这一点。或者&#39; ShortVersion.json&#39;我在链接中附加的文件。 希望这能解释更多信息。

所以问题是: - 任何人都可以帮助解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

您可以使用SelectTokens方法。请注意false作为第二个参数 - 如果找不到元素,请不要生成错误。

var jObject = JObject.Parse(jString);
var trList = jObject["tbody"]["tr"];
string[] names = trList.SelectMany(tr => tr.SelectTokens("td[0].a.#text", false))
                       .Select(t => t.Value<string>())
                       .ToArray();

答案 1 :(得分:0)

您可以像这样使用 LINQ 轻松查询

考虑这个 JSON

{
    "items": [
        {
            "id": "10",
            "name": "one"
        },
        {
            "id": "12",
            "name": "two"
        }
    ]
}

像这样把它放在一个名为 json 的变量中,

JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");

您可以使用以下 LINQ 查询从名称为 "one" 的项目中选择所有 ID

var Ids =
    from item in json["items"]
    where (string)item["name"] == "one"
    select item["id"];