JContainer,JObject,JToken和Linq混淆

Jaz*_*mov 44 c# linq json json.net

我无法理解时使用JContainer,JObjectJToken.我理解由"标准" JObject组成的JProperties,它JToken是所有JToken类型的基本抽象类,但我不明白JContainer.

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

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

string json;
using (StreamReader reader = new StreamReader(@"myjsonfile.json"))
{
    json = reader.ReadToEnd();
}
Run Code Online (Sandbox Code Playgroud)

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

JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);
Run Code Online (Sandbox Code Playgroud)

在我的JSON数据(由JSON表示的字符串)中,我有三个对象 - 顶级对象看起来类似于:

{
  "Object1" : { ... },
  "Object2" : { ... },
  "Object3" : { ... }
}
Run Code Online (Sandbox Code Playgroud)

每个对象都由各种标记(数组,字符串,其他对象等)组成,因此它是动态JSON.(我使用省略号作为占位符,而不是用大量JSON数据混淆这个问题.)

我要处理"Object1","Object2""Object3"单独使用LINQ,但是.所以,理想情况下,我想要这样的事情:

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

但上述行失败了.

我用var上面的,因为我不知道我应该使用什么样的对象类型:JContainer,JObjectJToken!只是让你知道我想要做什么,一旦jsonObject#正确分配了上述变量,我想使用LINQ来查询它们包含的JSON.这是一个非常简单的例子:

var query = from p in jsonObject1
   where p.Name == "Name1"
   select p
Run Code Online (Sandbox Code Playgroud)

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

我发现如果我使用:

// this line WORKS 
var jsonObject1 = ((JObject)jsonWork).["Object1"];
Run Code Online (Sandbox Code Playgroud)

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

我不清楚何时/为什么一个人会JContainer在看起来JTokenJObject对象很好地使用LINQ 时使用它.目的是JContainer什么?

Bri*_*ers 222

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)
Run Code Online (Sandbox Code Playgroud)

所以你看,a a ,一个. JObject JContainerJToken

这是基本的经验法则:

  • 如果您知道自己有一个对象(用花括号{}JSON表示),请使用JObject
  • 如果你知道你有一个数组或列表(由方括号表示[],使用)JArray
  • 如果您知道自己具有原始值,请使用 JValue
  • 如果您不知道您拥有什么样的令牌,或者希望能够以一般方式处理上述任何一种令牌,请使用JToken.然后,您可以检查其Type属性以确定它是什么类型的标记并适当地转换它.

  • 打印并将其放入我的办公室.多谢兄弟! (7认同)
  • 这个答案是最有用的,我到处都看他们都是如何联系的,并且bam!谢谢你,非常感谢一个彻底的tid位. (5认同)

Eli*_*bel 19

JContainer是具有子项的JSON元素的基类.JObject,JArray,JPropertyJConstructor所有从它继承.

例如,以下代码:

(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
Run Code Online (Sandbox Code Playgroud)

会抛出一个InvalidCastException,但是如果你把它投到一个JContainer,那就没事了.

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

var jsonWork = JObject.Parse(json);
var jsonObject1 = o["Object1"];
Run Code Online (Sandbox Code Playgroud)

  • JToken是所有JSON元素的基类。您只应对希望在字符串中包含的元素类型使用Parse方法。如果您不知道它是什么,请使用JToken,然后将其向下转换为JObject,JArray等。在这种情况下,您始终希望使用JObject,因此请使用它。仅当您要枚举子项而不关心父项是什么时,使用JContainer才有用。 (2认同)