2014-03-26 125 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