根据Winforms中的json文本动态创建树视图

我正在构建一个从外部源获取运行时JSON消息的应用程序。

我对消息文本的结构一无所知。

我想获取这个JSON文本,将其呈现为树视图(或类似的东西,关于UI),在我刚刚动态创建的树视图中编辑此JSON,并将文本发送回源。

我真的不知道从哪里开始……有什么建议吗?

private void btn_Convert_MouseClick(object sender, MouseEventArgs e) { try { string json = rbt_display.Text; JObject obj = JObject.Parse(json); tvw_display.Nodes.Clear(); TreeNode parent = Json2Tree(obj); parent.Text = "Root Object"; tvw_display.Nodes.Add(parent); } catch (Exception ex) { MessageBox.Show(ex.Message, "ERROR"); } } private TreeNode Json2Tree(JObject obj) { //create the parent node TreeNode parent = new TreeNode(); //loop through the obj. all token should be pair foreach (var token in obj) { //change the display Content of the parent parent.Text = token.Key.ToString(); //create the child node TreeNode child = new TreeNode(); child.Text = token.Key.ToString(); //check if the value is of type obj recall the method if (token.Value.Type.ToString() == "Object") { // child.Text = token.Key.ToString(); //create a new JObject using the the Token.value JObject o = (JObject)token.Value; //recall the method child = Json2Tree(o); //add the child to the parentNode parent.Nodes.Add(child); } //if type is of array else if (token.Value.Type.ToString() == "Array") { int ix = -1; // child.Text = token.Key.ToString(); //loop though the array foreach (var itm in token.Value) { //check if value is an Array of objects if (itm.Type.ToString() == "Object") { TreeNode objTN = new TreeNode(); //child.Text = token.Key.ToString(); //call back the method ix++; JObject o = (JObject)itm; objTN = Json2Tree(o); objTN.Text = token.Key.ToString() + "[" + ix + "]"; child.Nodes.Add(objTN); //parent.Nodes.Add(child); } //regular array string, int, etc else if(itm.Type.ToString() == "Array") { ix++; TreeNode dataArray = new TreeNode(); foreach (var data in itm) { dataArray.Text = token.Key.ToString() + "[" + ix + "]"; dataArray.Nodes.Add(data.ToString()); } child.Nodes.Add(dataArray); } else { child.Nodes.Add(itm.ToString()); } } parent.Nodes.Add(child); } else { //if token.Value is not nested // child.Text = token.Key.ToString(); //change the value into N/A if value == null or an empty string if (token.Value.ToString() == "") child.Nodes.Add("N/A"); else child.Nodes.Add(token.Value.ToString()); parent.Nodes.Add(child); } } return parent; } sample json { "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 25, "height_cm": 167.6, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": [], "spouse": null } 

注意:此示例使用NewtonSoft Json。 右键单击解决方案,然后单击“管理NuGet包”以安装引用。

此代码将处理JArray或JObject作为输入:

  string jsonString = "your json string here"; string rootName = "root", nodeName = "node"; JContainer json; try { if (jsonString.StartsWith("[")) { json = JArray.Parse(jsonString); treeView1.Nodes.Add(Utilities.Json2Tree((JArray)json, rootName, nodeName)); } else { json = JObject.Parse(jsonString); treeView1.Nodes.Add(Utilities.Json2Tree((JObject)json, text)); } } catch(JsonReaderException jre) { MessageBox.Show("Invalid Json."); } public class Utilities { public static TreeNode Json2Tree(JArray root, string rootName = "", string nodeName="") { TreeNode parent = new TreeNode(rootName); int index = 0; foreach(JToken obj in root) { TreeNode child = new TreeNode(string.Format("{0}[{1}]", nodeName, index++)); foreach (KeyValuePair token in (JObject)obj) { switch (token.Value.Type) { case JTokenType.Array: case JTokenType.Object: child.Nodes.Add(Json2Tree((JObject)token.Value, token.Key)); break; default: child.Nodes.Add(GetChild(token)); break; } } parent.Nodes.Add(child); } return parent; } public static TreeNode Json2Tree(JObject root, string text = "") { TreeNode parent = new TreeNode(text); foreach (KeyValuePair token in root) { switch (token.Value.Type) { case JTokenType.Object: parent.Nodes.Add(Json2Tree((JObject)token.Value, token.Key)); break; case JTokenType.Array: int index = 0; foreach(JToken element in (JArray)token.Value) { parent.Nodes.Add(Json2Tree((JObject)element, string.Format("{0}[{1}]", token.Key, index++))); } if (index == 0) parent.Nodes.Add(string.Format("{0}[ ]", token.Key)); //to handle empty arrays break; default: parent.Nodes.Add(GetChild(token)); break; } } return parent; } private static TreeNode GetChild(KeyValuePair token) { TreeNode child = new TreeNode(token.Key); child.Nodes.Add(string.IsNullOrEmpty(token.Value.ToString()) ? "n/a" : token.Value.ToString()); return child; } } 

那里有很多问题,真的。 如果你真的需要每个部分的指导,那么在这里尝试回答是很多的。

有一些用于读取JSON结构的类,随时可用。 由于Yosi间接链接,有JSON.net

一旦您可以阅读JSON,您就可以使用它来构建TreeView

编辑很简单,因为TreeView具有LabelEdit属性,支持就地编辑。 从那里开始,只需要对此作出反应并跟踪变化。 或者也许最后一举将它全部读回来,你的选择。 无论哪种方式, TreeView都有诸如BeforeLabelEditAfterLabelEdit等事件,所有这些都可以在上面的TreeView链接上找到。

你可以试试这段代码:

 public class JsonTag { public JsonTag(JsonReader reader) { TokenType = reader.TokenType; Value = reader.Value; ValueType = reader.ValueType; } public JsonToken TokenType { get; set; } public object Value { get; set; } public Type ValueType { get; set; } } private void JsonToTreeview(string json) { tvwValue.BeginUpdate(); var parentText = string.Empty; TreeNodeCollection parentNodes = tvwValue.Nodes; TreeNode current = null; tvwValue.Nodes.Clear(); var reader = new JsonTextReader(new StringReader(json)); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.None: break; case JsonToken.StartObject: current = new TreeNode("{}") { Tag = new JsonTag(reader) }; parentNodes.Add(current); parentNodes = current.Nodes; break; case JsonToken.StartArray: current = new TreeNode("[]") { Tag = new JsonTag(reader) }; parentNodes.Add(current); if (current.PrevNode != null) { if (((JsonTag)current.PrevNode.Tag).TokenType == JsonToken.PropertyName) current.Parent.Text += "[]"; parentText = current.Parent.Text; if (current.Parent.Parent.Text.Length > 2) parentText = ", " + parentText; current.Parent.Parent.Text = current.Parent.Parent.Text.Insert(current.Parent.Parent.Text.Length - 1, parentText); } parentNodes = current.Nodes; break; case JsonToken.StartConstructor: break; case JsonToken.PropertyName: current = new TreeNode("\"" + reader.Value + "\" : "); parentNodes.Add(current); if (current.PrevNode != null) current.PrevNode.Text += ","; parentNodes = current.Nodes; current = new TreeNode(reader.Value.ToString()) { Tag = new JsonTag(reader) }; parentNodes.Add(current); break; case JsonToken.Comment: break; case JsonToken.Raw: break; case JsonToken.Date: case JsonToken.Integer: case JsonToken.Float: case JsonToken.Boolean: case JsonToken.String: var readerValue = ""; if (reader.TokenType == JsonToken.String) readerValue = "\"" + reader.Value + "\""; else readerValue = reader.Value.ToString(); current = new TreeNode(readerValue) { Tag = new JsonTag(reader) }; parentNodes.Add(current); current.Parent.Text += readerValue; parentText = current.Parent.Text; if (current.Parent.Parent.Text.Length > 2) parentText = ", " + parentText; current.Parent.Parent.Text = current.Parent.Parent.Text.Insert(current.Parent.Parent.Text.Length - 1, parentText); if (((JsonTag)current.PrevNode.Tag).TokenType == JsonToken.PropertyName) current = current.Parent; current = current.Parent; parentNodes = current.Nodes; break; case JsonToken.Bytes: break; case JsonToken.Null: break; case JsonToken.Undefined: break; case JsonToken.EndObject: if (current.FirstNode.Tag != null && ((JsonTag)current.FirstNode.Tag).TokenType == JsonToken.PropertyName) current = current.Parent; current = current.Parent; if (current == null) parentNodes = tvwValue.Nodes; else parentNodes = current.Nodes; break; case JsonToken.EndArray: if (((JsonTag)current.PrevNode.Tag).TokenType == JsonToken.PropertyName) current = current.Parent; current = current.Parent; if (current == null) parentNodes = tvwValue.Nodes; else parentNodes = current.Nodes; break; case JsonToken.EndConstructor: break; default: throw new ArgumentOutOfRangeException(); } } tvwValue.EndUpdate(); }