I am building an application that gets in run-time JSON message from external source.
I don\'t know anything about the structure of the message text.
I want
Lots of questions there, really. If you really need guidance on every part of that then it's a lot to try and answer here.
There are classes for reading JSON structures, readily available. As Yosi indirectly linked, there's JSON.net
Once you can read the JSON, you can use it to construct the TreeView
Editing is simple enough, as the TreeView
has a property for LabelEdit
that supports editing in-place. From there, it's just a matter of reacting to that and keeping track of the changes. Or perhaps reading it all back out in one fell swoop at the end, your choice. Either way, the TreeView
has events such as BeforeLabelEdit
, AfterLabelEdit
, etc., all of which can be found on the TreeView
link above.
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<key, value>
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
}
Note: This example uses NewtonSoft Json. Right-click solution and click manage NuGet packages to install the reference.
This code will handle both JArray or JObject as an input:
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<string, JToken> 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<string, JToken> 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<string, JToken> token)
{
TreeNode child = new TreeNode(token.Key);
child.Nodes.Add(string.IsNullOrEmpty(token.Value.ToString()) ? "n/a" : token.Value.ToString());
return child;
}
}
You can try this code :
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();
}