JContainer,JObject,JToken和Linq混淆

我无法理解何时使用JContainerJObjectJToken 。 我从“标准”中JObject是由JObject组成的,而JToken是所有JToken类型的基本抽象类,但我不理解JContainer

我正在使用C#,我刚买了LinqPad Pro 5。

我在一个文件中有一个JSON数据源,所以我使用这个语句成功地反序列化了该文件的内容:

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

那时,我接受JSON字符串对象并将其反序列化为JObject (这可能是我的错误 – 也许我需要使jsonWork成为JTokenJContainer ?):

 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因为我不知道我应该使用什么对象类型: JContainerJObjectJToken ! 只是让你知道我想要做什么,一旦正确分配了上面的jsonObject#变量,我想使用LINQ来查询它们包含的JSON。 这是一个非常简单的例子:

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

当然,我的LINQ最终将在jsonObject变量中过滤JSON数组,对象,字符串等。 我想一旦我开始,我可以使用LinqPad帮助我使用LINQ过滤JSON。

我发现如果我使用:

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

然后我在jsonObject1得到一个JObject类型。 这是正确的方法吗?

我不清楚何时/为什么当JTokenJObject对象看起来JToken使用时,会使用JContainerJContainer的目的是JContainer

JContainer是具有子项的JSON元素的基类。 JObjectJArrayJPropertyJConstructor都inheritance自它。

例如,以下代码:

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

会抛出一个InvalidCastException ,但是如果你把它转换为JContainer ,那就没关系。

关于你的原始问题,如果你知道你在顶级有一个JSON对象,你可以使用:

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

在大多数情况下,您并不需要担心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属性以确定它是什么类型的令牌并适当地转换它。