2016-07-25 171 views
5

*在編寫/編輯這個問題時,我開始回答我自己的問題。閱讀更多的細節,但我的實際問題是在最後,粗體。謝謝! *JContainer,JObject,JToken和Linq混淆

我無法理解何時使用JContainer,JObject和JToken。我從「標準」瞭解到JObject由JProperties組成,並且JToken是所有JToken類型的基本抽象類,但我不瞭解JContainer。

我使用C#和我剛買LinqPad臨5.

我在文件中的JSON數據源,所以我成功反序列化文件的內容使用此語句:

string json; 
using (StreamReader reader = new StreamReader(@"myjsonfile.json")) 
{ 
    json = reader.ReadToEnd(); 
} 

在這一點上,我走的JSON字符串對象,並將其反序列化到JObject(這可能是我的錯誤 - 也許我需要一個jsonWork或JToken JContainer?):

JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json); 

在我的JSON數據(由JSON表示的字符串),我有三個對象 - 頂層對象類似於此:

{ 
    "Object1" : { ... }, 
    "Object2" : { ... }, 
    "Object3" : { ... } 
} 

每個對象都是由各種記號的(數組,字符串,其它的目的,等),所以它是動態的JSON。 (我使用橢圓作爲佔位符,而不是將許多JSON數據混淆在這個問題上。)

但是,我想分別使用Linq處理「Object1」,「Object2」和「Object3」。所以,理想情況下,我想這樣的事情:

// these lines DO NOT work  
var jsonObject1 = jsonWork.Children()["Object1"] 
var jsonObject2 = jsonWork.Children()["Object2"] 
var jsonObject3 = jsonWork.Children()["Object3"] 

但上述線路失敗。

我上面使用了「var」,因爲我不知道應該使用什麼對象類型:JContainer,JObject或JToken!只要你知道我想要做什麼,一旦上面的jsonObject#變量被正確賦值,我想用Linq來查詢它們包含的JSON。這是一個很簡單的例子:

var query = from p in jsonObject1 
    where p.Name == "Name1" 
    select p 

當然,我的LINQ最終將篩選JSON數組,對象,字符串等,在可變的JSONObject ......我想一旦我走了,我可以用LinqPad幫助我使用Linq過濾JSON(雖然我可能會有更多的後續問題,但我會在這個網站上發佈它們)...

任何想法?

******增加的細節: OK,我發現,如果我使用:

// this line WORKS 
var jsonObject1 = ((JObject)jsonWork).["Object1"]; 

然後我得到了一個jsonObject1型JObject。這是正確的方法嗎?

問: 目前還不清楚我的時候/爲什麼當它似乎JToken和JObject對象使用LINQ工作得很好...什麼是JContainer的目的,應當使用JContainer ???

回答

7

JContainer是具有子項目的JSON元素的基類。JObjectJArrayJPropertyJConstructor都從它繼承。

例如,下面的代碼:

(JObject)JsonConvert.DeserializeObject("[1, 2, 3]") 

將拋出一個InvalidCastException,但如果你把它轉換爲JContainer,這將是罰款。

關於你原來的問題,如果你知道你必須在頂層的JSON對象,你可以使用:

var jsonWork = JObject.Parse(json); 
var jsonObject1 = o["Object1"]; 
+0

在您的第一個示例中,也使用(JToken)JsonConvert.DeserializeObject(「[1,2,3]」)。我從其他答案中看到,JContainer可以容納JToken可以包含的所有內容,包括其他JTokens。這是唯一的區別嗎?你的第二個例子有用,謝謝! – Jazimov

+1

JToken是所有JSON元素的基類。您應該使用Parse方法來預測字符串中的元素類型。如果你不知道它是什麼,那麼使用JToken,然後你就可以將它轉換成JObject,JArray等等。在這種情況下,你總是期待一個JObject,所以使用它。如果您想枚舉子項而不關心父項是什麼,那麼使用JContainer只會非常有用。 –

50

你並不真正需要擔心在大多數情況下,約JContainer。它有助於將LINQ-to-JSON組織和組織成結構良好的代碼。

JToken層次結構是這樣的:

JToken    - abstract base class  
    JContainer  - abstract base class of JTokens that can contain other JTokens 
     JArray  - represents a JSON array (contains an ordered list of JTokens) 
     JObject  - represents a JSON object (contains a collection of JProperties) 
     JProperty - represents a JSON property (a name/JToken pair inside a JObject) 
    JValue   - represents a primitive JSON value (string, number, boolean, null) 

所以你看,一個JObject一個JContainer,這一個JToken

這裏的拇指的基本規則:

  • 如果你知道你有一個對象(由大括號{和JSON }表示),使用JObject
  • 如果你知道你有一個數組或列表(方括號[]表示),使用JArray
  • 如果你知道你有一個原始值,用JValue
  • 如果您不知道你擁有什麼類型的令牌,或者希望能夠以一般方式處理上述任何情況,請使用JToken。然後,您可以檢查其屬性Type,以確定它是什麼類型的標記並進行適當的轉換。
+0

這個答案是最豐富的,我已經看遍了他們所有的關係,並且砰!謝謝你,真的很感謝徹底tid位。 – Chopnut