2016-12-08 52 views
1

我有這樣的JSON:如何從指定級別獲取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 ! 
     ] 
     } 
    ] 
} 

我需要把價值「節點」元素,其中我是2級「文本」等於「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")); 

我不明白怎麼「點」在查詢工作......我只知道,當你輸入2「點」它瀏覽整個JSON ...有沒有辦法只查詢一個特定的縮進級別?使用Newtonsoft.Json包

+0

你可以把它反序列化類,並把它,是這種方法好了嗎? – mybirthname

+0

不,這是不好的,實際上我生成這個JSON,我需要把數據放在「節點」元素,我在第2級,「文本」等於「富」... – Thomas

回答

3

我想通了,是的,我們可以指定一個水平壓痕,當我們想查詢文本平原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節和jsonPath補充一點:$.treeview[*].nodes[*].nodes[*].text

這是你如何能得到所需的"level of identation"'foo'值,而不在陣列中指定的任何指標,只要使用這個'*',而不是一個int

1

這是很容易的不僅僅是簡單的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; } 
} 

OUTPUT:

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 

EDIT2:

使用您的實際JSON對象需要一個TreeView類,以及...

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; } 
} 

OUTPUT:

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": [] 
    } 
    ] 
} 
+0

我同意,但如果我有多個「foo」值在不同的嵌套級別?我只想在「text」等於「foo」的特定級別上使用「text」元素,在您瀏覽所有「n.text」的代碼示例中,其值等於「foo」 – Thomas

+0

@Thomasa請參閱我的編輯 –

+0

好的方法,我會試試這個! – Thomas

1

你需要指定正確的路徑到「節點」數組。試試這個:

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"))); 
+0

當然,但你在這裏指定一個索引「treeview [2]」(2)實際上,我不知道它在哪裏...... – Thomas

+0

如果你沒有特定的節點你想插入數據是,你將如何找到它...?您需要知道JSON數據的結構才能使用JSONPath來查找特定節點。 – mm8

+0

是的,我只知道水平縮進,我知道在這個水平上只能有一個「文本」值 – Thomas

相關問題