2016-07-25 56 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