2014-03-26 94 views
0

我想在json字符串中创建一个Linq查询。用Linq查询复杂的Json

关于我想要做什么的信息很少。在工作中,我们有一个基于Web的时间表系统,它不支持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": "[email protected]", 
      "#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"); 

我可以得到 '#text',这是* 'NAME3' 的价值。

但是,如果我尝试下面的代码(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循环的第一次迭代打破“无法在Newtonsoft.Json.Linq访问子值.JValue”。我现在真的是什么导致了这个问题,但我不知道如何解决它。问题是并不是jCollection中的每个标记都有一个'td'对象,即使该标记具有'td'对象,它也不总是具有标记'a'。您可以在链接中附加的'TheWholeJsonString.json'或'ShortVersion.json'文件中查看。 希望这会解释更多信息。

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

+0

[LINQ的针对JSON数据查询(更新信息)]的复制(http://stackoverflow.com/questions/22623205/linq-query-against-json-data-updated-info)。你应该编辑以前的帖子并投票重新开启。 –

+0

@GertArnold嗨格特,我对前面的问题进行了部分更新,并要求几次重新开放而没有任何回应,我不想对其他想尝试帮助的ppl感到恼火,这就是为什么我决定提交一个新的问题。接受我的道歉。 – DreamNet

回答

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(); 
+0

感谢这个刚刚救了我一天的人,我对你的代码做了一些修改(添加了.where的条件)以满足我的需求。再次感谢。 – DreamNet