4

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

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

我想获取这个 JSON 文本,将其渲染到树视图(或类似的 UI 相关),在我刚刚动态创建的树视图中编辑这个 JSON,然后将文本发送回源。

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

4

5 回答 5

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

注意:此示例使用 NewtonSoft Json。右键单击解决方案并单击管理 NuGet 包以安装参考。

于 2015-03-25T15:52:34.533 回答
4

此代码将处理 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<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;
    }

}
于 2017-03-06T18:59:40.903 回答
1

你可以试试这段代码:

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();
}
于 2014-08-19T08:24:42.440 回答
0

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

有用于读取 JSON 结构的类,现成可用。正如 Yosi 间接链接的那样,有JSON.net

一旦可以读取 JSON,就可以使用它来构造TreeView

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

于 2013-09-12T19:50:07.290 回答
0

从包管理器控制台:

PM> Install-Package Newtonsoft.Json

然后清理@vinceg 的答案,我推出了一个静态类:

    using Newtonsoft.Json.Linq;
    using System.Collections.Generic;
    using System.Windows.Forms;
    
    public static class clsJSON2treeview
    {
    
        /// <summary>Parse JSON string, individual tokens become TreeView Nodes ~mwr</summary>
        /// <param name="oTV">TreeView control to display parsed JSON</param>
        /// <param name="sJSON">Incoming JSON string</param>
        /// <param name="rootName">Title of top node in TreeView wrapping all JSON</param>
        public static void JsonToTreeview(TreeView oTV, string sJSON, string rootName)
        {
            JContainer json = sJSON.StartsWith("[")
                            ? (JContainer)JArray.Parse(sJSON)
                            : (JContainer)JObject.Parse(sJSON);
    
            oTV.Nodes.Add(Ele2Node(json, rootName));
        }
    
        private static TreeNode Ele2Node(object oJthingy, string text = "")
        {
            TreeNode oThisNode = new TreeNode(text);
    
            switch (oJthingy.GetType().Name) //~mwr could not find parent object for all three JObject, JArray, JValue
            {
                case "JObject":
                    foreach (KeyValuePair<string, JToken> oJtok in (JObject)oJthingy)
                        oThisNode.Nodes.Add(Ele2Node(oJtok.Value, oJtok.Key));
                    break;
                case "JArray":
                    int i = 0;
                    foreach (JToken oJtok in (JArray)oJthingy)
                        oThisNode.Nodes.Add(Ele2Node(oJtok, string.Format("[{0}]", i++)));
    
                    if (i == 0) oThisNode.Nodes.Add("[]"); //to handle empty arrays
                    break;
                case "JValue":
                    oThisNode.Nodes.Add(new TreeNode(oJthingy.ToString()));
                    break;
                default:
                    throw new System.Exception("clsJSON2Treeview can't interpret object:" + oJthingy.GetType().Name);
            }
    
            return oThisNode;
        }
    }
于 2021-10-28T23:19:27.707 回答