我无法理解何时使用JContainer
,JObject
和JToken
。我理解"标准" JObject
由JProperties
组成,JToken
是所有JToken
类型的基本抽象类,但我不理解JContainer
我正在使用C#而我刚买了LinqPad Pro 5.
我在文件中有一个JSON数据源,所以我使用这个语句成功地反序列化了该文件的内容:
string json;
using (StreamReader reader = new StreamReader(@"myjsonfile.json"))
{
json = reader.ReadToEnd();
}
此时,我接受JSON字符串对象并将其反序列化为JObject
(这可能是我的错误 - 也许我需要将jsonWork
设为JToken
或{ {1}}):
JContainer
在我的JSON数据(由JSON表示的字符串)中,我有三个对象 - 顶级对象看起来与此类似:
JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);
每个对象都由各种标记(数组,字符串,其他对象等)组成,因此它是动态JSON。 (我使用省略号作为占位符而不是用大量JSON数据混淆这个问题。)
但是,我想使用LINQ分别处理{
"Object1" : { ... },
"Object2" : { ... },
"Object3" : { ... }
}
,"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
变量,我想使用LINQ来查询它们包含的JSON。这是一个非常简单的例子:
jsonObject#
当然,我的LINQ最终将在var query = from p in jsonObject1
where p.Name == "Name1"
select p
变量中过滤JSON数组,对象,字符串等。我想,一旦开始,我可以使用LinqPad帮助我使用LINQ过滤JSON。
我发现如果我使用:
jsonObject
然后我在// this line WORKS
var jsonObject1 = ((JObject)jsonWork).["Object1"];
中获得JObject
类型。这是正确的方法吗?
我不清楚当jsonObject1
和JContainer
对象看起来很好地使用LINQ时,/为什么会使用JToken
。 JObject
的目的是什么?
答案 0 :(得分:183)
在大多数情况下,您并不需要担心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
。
这是基本的经验法则:
答案 1 :(得分:14)
JContainer
是具有子项的JSON元素的基类。 JObject
,JArray
,JProperty
和JConstructor
都是从它继承的。
例如,以下代码:
(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")
会抛出InvalidCastException
,但是如果你将其投放到JContainer
,那就没关系了。
关于您的原始问题,如果您知道顶层有JSON对象,则可以使用:
var jsonWork = JObject.Parse(json);
var jsonObject1 = o["Object1"];
答案 2 :(得分:0)
大多数示例都具有简单的json,并且我多次用Google搜索“ C#Newtonsoft解析JSON”。
这是我刚被要求解析为CSV的json文件的一部分。公司名称值嵌套在许多数组/对象中,因此在这方面它是半复杂的。
{
"page": {
"page": 1,
"pageSize": 250
},
"dataRows": [
{
"columnValues": {
"companyName": [
{
"name": "My Awesome Company",
}
]
}
}
]
}
var jsonFilePath = @"C:\data.json";
var jsonStr = File.ReadAllText(jsonFilePath);
// JObject implementation for getting dataRows JArray - in this case I find it simpler and more readable to use a dynamic cast (below)
//JObject jsonObj = JsonConvert.DeserializeObject<JObject>(jsonStr);
//var dataRows = (JArray)jsonObj["dataRows"];
var dataRows = ((dynamic)JsonConvert.DeserializeObject(jsonStr)).dataRows;
var csvLines = new List<string>();
for (var i = 0; i < dataRows.Count; i++)
{
var name = dataRows[i]["columnValues"]["companyName"][0]["name"].ToString();
// dynamic casting implemntation to get name - in this case, using JObject indexing (above) seems easier
//var name2 = ((dynamic)((dynamic)((dynamic)dataRows[i]).columnValues).companyName[0]).name.ToString();
csvLines.Add(name);
}
File.WriteAllLines($@"C:\data_{DateTime.Now.Ticks}.csv", csvLines);