如何从指定级别获取 json 节点?
How can i get a json node from a specified level?
我有这个json:
{
"treeview":[
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
{
"text":"blah",
"nodes":[
{
"text":"foo",
"nodes":[
// I need to put data in here !!!
]
}
]
}
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"foo",
"nodes":[
// Not here !
]
}
]
}
我需要给 "nodes" 元素赋值,其中 我在第 2 层 并且 "text" 等于 "foo".
这是我目前尝试过的方法:
var json = myJson;
// First approach
var selector = (JArray)json.SelectTokens($"$..treeview[?(@.text == 'foo')]");
// Second approach
var selector2 = (JArray)json.SelectToken($"$.treeview[?(@...text == 'foo')]");
selector.Add(new JObject(new JProperty("text", "myValue"));
我不明白查询中的 "dot" 是如何工作的...我只知道当您键入 2 "dot" 时它会浏览整个 JSON... 是有没有办法只查询特定的缩进级别?
使用对象比单纯的 json 文本要容易得多...
使用 Newtonsoft.Json 包...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\", \"nodes\": []}, {\"text\":\"bar\", \"nodes\": []}, {\"text\":\"foo\", \"nodes\": []}]}";
//This is the root node
var firstLevelNodes = JsonConvert.DeserializeObject<Node>(jsonstring);
//All the nodes in the root nodes node collection
var secondLevelNodes = firstLevelNodes.nodes;
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("First Level Nodes: \n" + JsonConvert.SerializeObject(firstLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Second Level Nodes: \n" + JsonConvert.SerializeObject(secondLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Third Level Nodes: \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
secondLevelNodes.First().nodes = new List<Node> { new Node { text = "new node" , nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("Third Level Nodes (with new node): \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
Console.ReadLine();
}
}
public static class JSONExtensions
{
public static string PrettyPrint(this string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
输出:
First Level Nodes:
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
Second Level Nodes:
[
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
Third Level Nodes:
[]
Third Level Nodes (with new node):
[
{
"text": "new node",
"nodes": []
}
]
编辑:
因此,如果您只想要具有文本 foo 的二级节点,只需使用..
var secondLevelFooNodes = secondLevelNodes.Where(sln=>sln.text == "foo");
//then use these nodes
编辑 2:
使用您的实际 JSON 对象还需要 TreeView Class...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}";
//This is the root node
var treeView = JsonConvert.DeserializeObject<TreeView>(jsonstring);
//All the nodes in the root nodes node collection
var firstLevelNodes = treeView.treeview;
//All of the nodes in the collections of the first level nodes
var secondLevelNodes = firstLevelNodes.SelectMany(fln => fln.nodes);
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("The TreeView: \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
thirdLevelNodes.First(sln => sln.text == "foo").nodes = new List<Node> { new Node { text = "new node", nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("The TreeView (with new node): \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
Console.ReadLine();
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
[Serializable]
public class TreeView
{
public IEnumerable<Node> treeview { get; set; }
}
输出:
The TreeView:
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
The TreeView (with new node):
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": [
{
"text": "new node",
"nodes": []
}
]
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
您需要指定 "nodes" 数组的正确路径。试试这个:
JObject json = JObject.Parse("{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}");
JArray array = (JArray)json.SelectToken("treeview[2].nodes[0].nodes[0].nodes");
array.Add(new JObject(new JProperty("text", "myValue")));
我明白了,是的,当我们想在纯文本中查询 json 时,我们可以指定一个级别缩进,方法如下:
var json = myJson;
var selector = (JArray)json.SelectTokens($"$.treeview[*].nodes[*].nodes[(@.text =='foo')].nodes");
selector.Add(new JObject(new JProperty("text", "myValue")));
你可以在这里测试: http://jsonpath.com/
复制我在 json 部分中的 json 示例并将其添加到 json 路径中:$.treeview[*].nodes[*].nodes[*].text
这就是如何在不指定数组中任何索引的情况下获得所需 "level of identation"
中的 'foo'
值的方法,只需使用此 '*'
而不是 int
我有这个json:
{
"treeview":[
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"blah",
"nodes":[
{
"text":"blah",
"nodes":[
{
"text":"foo",
"nodes":[
// I need to put data in here !!!
]
}
]
}
]
},
{
"text":"blah",
"nodes":[
]
},
{
"text":"foo",
"nodes":[
// Not here !
]
}
]
}
我需要给 "nodes" 元素赋值,其中 我在第 2 层 并且 "text" 等于 "foo".
这是我目前尝试过的方法:
var json = myJson;
// First approach
var selector = (JArray)json.SelectTokens($"$..treeview[?(@.text == 'foo')]");
// Second approach
var selector2 = (JArray)json.SelectToken($"$.treeview[?(@...text == 'foo')]");
selector.Add(new JObject(new JProperty("text", "myValue"));
我不明白查询中的 "dot" 是如何工作的...我只知道当您键入 2 "dot" 时它会浏览整个 JSON... 是有没有办法只查询特定的缩进级别?
使用对象比单纯的 json 文本要容易得多...
使用 Newtonsoft.Json 包...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\", \"nodes\": []}, {\"text\":\"bar\", \"nodes\": []}, {\"text\":\"foo\", \"nodes\": []}]}";
//This is the root node
var firstLevelNodes = JsonConvert.DeserializeObject<Node>(jsonstring);
//All the nodes in the root nodes node collection
var secondLevelNodes = firstLevelNodes.nodes;
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("First Level Nodes: \n" + JsonConvert.SerializeObject(firstLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Second Level Nodes: \n" + JsonConvert.SerializeObject(secondLevelNodes).PrettyPrint());
Console.WriteLine();
Console.WriteLine("Third Level Nodes: \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
secondLevelNodes.First().nodes = new List<Node> { new Node { text = "new node" , nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("Third Level Nodes (with new node): \n" + JsonConvert.SerializeObject(thirdLevelNodes).PrettyPrint());
Console.ReadLine();
}
}
public static class JSONExtensions
{
public static string PrettyPrint(this string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
输出:
First Level Nodes:
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
Second Level Nodes:
[
{
"text": "foo",
"nodes": []
},
{
"text": "bar",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
Third Level Nodes:
[]
Third Level Nodes (with new node):
[
{
"text": "new node",
"nodes": []
}
]
编辑:
因此,如果您只想要具有文本 foo 的二级节点,只需使用..
var secondLevelFooNodes = secondLevelNodes.Where(sln=>sln.text == "foo");
//then use these nodes
编辑 2:
使用您的实际 JSON 对象还需要 TreeView Class...
class Program
{
static void Main(string[] args)
{
var jsonstring = "{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}";
//This is the root node
var treeView = JsonConvert.DeserializeObject<TreeView>(jsonstring);
//All the nodes in the root nodes node collection
var firstLevelNodes = treeView.treeview;
//All of the nodes in the collections of the first level nodes
var secondLevelNodes = firstLevelNodes.SelectMany(fln => fln.nodes);
//All of the nodes in the collections of the second level nodes
var thirdLevelNodes = secondLevelNodes.SelectMany(sln => sln.nodes);
Console.WriteLine("The TreeView: \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
thirdLevelNodes.First(sln => sln.text == "foo").nodes = new List<Node> { new Node { text = "new node", nodes = new List<Node>() } };
Console.WriteLine();
Console.WriteLine("The TreeView (with new node): \n" + JsonConvert.SerializeObject(treeView, Formatting.Indented));
Console.ReadLine();
}
}
[Serializable]
public class Node
{
public string text { get; set; }
public IEnumerable<Node> nodes { get; set; }
}
[Serializable]
public class TreeView
{
public IEnumerable<Node> treeview { get; set; }
}
输出:
The TreeView:
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": []
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
The TreeView (with new node):
{
"treeview": [
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": []
},
{
"text": "blah",
"nodes": [
{
"text": "blah",
"nodes": [
{
"text": "foo",
"nodes": [
{
"text": "new node",
"nodes": []
}
]
}
]
}
]
},
{
"text": "blah",
"nodes": []
},
{
"text": "foo",
"nodes": []
}
]
}
您需要指定 "nodes" 数组的正确路径。试试这个:
JObject json = JObject.Parse("{\"treeview\":[{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"blah\",\"nodes\":[{\"text\":\"blah\",\"nodes\":[{\"text\":\"foo\",\"nodes\":[]}]}]},{\"text\":\"blah\",\"nodes\":[]},{\"text\":\"foo\",\"nodes\":[]}]}");
JArray array = (JArray)json.SelectToken("treeview[2].nodes[0].nodes[0].nodes");
array.Add(new JObject(new JProperty("text", "myValue")));
我明白了,是的,当我们想在纯文本中查询 json 时,我们可以指定一个级别缩进,方法如下:
var json = myJson;
var selector = (JArray)json.SelectTokens($"$.treeview[*].nodes[*].nodes[(@.text =='foo')].nodes");
selector.Add(new JObject(new JProperty("text", "myValue")));
你可以在这里测试: http://jsonpath.com/
复制我在 json 部分中的 json 示例并将其添加到 json 路径中:$.treeview[*].nodes[*].nodes[*].text
这就是如何在不指定数组中任何索引的情况下获得所需 "level of identation"
中的 'foo'
值的方法,只需使用此 '*'
而不是 int