簡體   English   中英

在反序列化JSON字符串時遇到麻煩

[英]Having trouble with deserializing a JSON String

對於目前正在處理的項目,我遇到了很多麻煩。 我從外部來源獲得JSON字符串。 我收到的JSON字符串如下:

{
    "PC_Station": [{
        "PLC_0": {
            "DB1": {
                "test123": 0
            },
            "STOP": false,
            "START": false,
            "Start_1": false,
            "Stop_1": false,
            "Led1": true,
            "Led2": false,
            "Led3": true,
            "Counter": 4002,
            "Sliderval": 0
        }
    }, {
        "PLC_1": {
            "DB1": {
                "test123": 0
            },
            "Led_1": false,
            "Led_2": false,
            "Led_3": false,
            "Led_4": false,
            "Tag1": true,
            "Tag2": false,
            "Tag3": true,
            "Counter": 4002,
            "randomNr": 0
        }
    }]
}

外部源是通過PLC設備(工業I / O)將其具有的所有變量發送到服務器的方式制成的。 服務器收集PLC設備的名稱以及它包含的所有變量,並將所有PLC設備添加到數組中,如上面的JSON中所示。

我需要什么:我正在嘗試用C#創建一個JSON Deserializer,以動態捕獲所有變量和變量名。 我將在我要分配的應用程序中使用它。 在Unity3d中用PLC變量填充GUI,但這與上下文無關。

我嘗試的最后一件事是:

static void Main(string[] args)
        {
            string json = "{\"PC_Station\": [{\"PLC_0\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}},{\"PLC_1\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}}]}";
            JObject root = JObject.Parse(json);
            dynamic pcstation = root["PC_Station"];
            for(int x = 0; x < pcstation.Count; x++)
            {
                Console.WriteLine(pcstation[x]);
            }
            Console.ReadLine();
        }

當僅在for循環中打印x時,我得到0和1作為輸出,這意味着有2個項目,也就是PC_station下數組中的兩個PLC設備。 我覺得我快到了。

我希望任何人都可以幫助我弄清楚我需要做什么,因為我快要瘋了。

編輯1:似乎我不太清楚我想要什么,您看到的是,我收到的示例JSON代碼來自兩個隨機PLC設備。 每個PLC都有自己的變量,因此我不能使用json2csharp生成的類的原因。 我想動態反序列化並使用從服務器接收的變量在Unity中可視化它們。

嘗試將兩個數組項轉換為列表,即可解決問題。 我曾經遇到過同樣的問題,並且已經解決了同樣的問題。 試試,如果它不起作用,請告訴我。 我將與您共享代碼。

您可以使用JToken解析此JSON,這使得可以輕松地遍歷屬性和訪問對象,而不必事先了解整個結構。

var json = @"{
""PC_Station"": [{
        ""PLC_0"": {
            ""DB1"": {
                ""test123"": 0
            },
            ""STOP"": false,
            ""START"": false,
            ""Start_1"": false,
            ""Stop_1"": false,
            ""Led1"": true,
            ""Led2"": false,
            ""Led3"": true,
            ""Counter"": 4002,
            ""Sliderval"": 0
        }
    }, {
        ""PLC_1"": {
            ""DB1"": {
                ""test123"": 0
            },
            ""Led_1"": false,
            ""Led_2"": false,
            ""Led_3"": false,
            ""Led_4"": false,
            ""Tag1"": true,
            ""Tag2"": false,
            ""Tag3"": true,
            ""Counter"": 4002,
            ""randomNr"": 0
        }
    }]
}";


var root = JToken.Parse(json);
int i = 0;
foreach (var item in root["PC_Station"].Values())
{
    Console.WriteLine("Item {0}: {1}", i++, item);
}

您可以輕松枚舉 JToken對象的屬性,例如

static void TraverseJToken(JToken jtoken)
{
    foreach (var value in jtoken.Values())
    {
        if (value.HasValues)
        {
            TraverseJToken(value);
        }
        else
        {
            Console.WriteLine(value.Path + ": " + value.ToObject<string>());
        }
    }
}

TraverseJToken(root);

您還可以選擇單個值和JSON樹的子集:

var Counter = root.SelectToken("PC_Station[0].PLC_0.Counter").Value<int>();
Console.WriteLine("Counter: " + Counter);

我想我了解您的問題。 如果您無法定義可用於將JSON映射到C#的C#類,則需要重新考慮它。 為什么不創建一個僅包含Dictionary<string,string>HashSet<string,string>的簡單C#類

如果您正在設計如何構造PLC的有效負載,則可以使其適合具有一些基本屬性的簡單C#類,以及用於創建不一致的變量的字典。

或者如果您想要dynamic類型行為, 請https://weblog.west-wind.com/posts/2012/Aug/30/Using-JSONNET-for-dynamic-JSON-parsing

JSON.parse convert json to  object.

Accessing Object Values. You can access the object values by using dot (.)

 for(int x = 0; x < pcstation.Count; x++)
            {
                Console.WriteLine(pcstation[x].PLC_0.DB1.test123);//0
                Console.WriteLine(pcstation[x].STOP);//false

 }

您可以使用Newtonsoft.json

string line = "{\"PC_Station\": [{\"PLC_0\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}},{\"PLC_1\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}}]}";
var files = JObject.Parse(line);
var recList = files.SelectToken("$..PC_Station").ToList();

    foreach (var item in recList)

    {
        for (int i = 0; i < item.Count(); i++)
        {
            Console.WriteLine(recList[i]);
        }
    }

設法解決了我的問題! 你們共享過時的信息,並編寫了大量的代碼。 但是,嘿,它有效:P。 這是我使用此處發布的建議想到的代碼:

using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;

public class generateUI : MonoBehaviour
{
    public static int size = 0;
    public static List<Dictionary<string, string>> abc = new List<Dictionary<string, string>>();
    public GameObject canvas;
    public GameObject Panel;
    public GameObject image;
    public GameObject imagetext;
    private float scaler = 0.0125f;
    void Start()
    {
        string json = "{\"PC_Station\": [{\"PLC_0\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}}]}";
        //string json = "{\"PC_Station\": [{\"PLC_0\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}},{\"PLC_1\": {\"DB1\": {\"test123\": 0}, \"STOP\": false, \"START\": false, \"Start_1\": false, \"Stop_1\": false, \"Led1\": true, \"Led2\": false, \"Led3\": true, \"Counter\": 4002, \"Sliderval\": 0}}]}";
        Panel.transform.SetParent(canvas.transform, false);
        var root = JToken.Parse(json);
        IterateJtoken(root);
        List<string> varz = new List<string>();
        foreach(var item in abc)
        {
            foreach(var it in item)
            {
                varz.Add(it.Key);
            }
        }




        GameObject[] tiles = new GameObject[size];
        GameObject[] texts = new GameObject[size];
        int tilenum = 0;
        for (int i = 0; i < size; i++)
        {
            tilenum++;
            tiles[i] = Instantiate(image, transform.position, transform.rotation);
            tiles[i].name = "tile"+tilenum;
            tiles[i].transform.SetParent(Panel.transform, false);
            texts[i] = Instantiate(imagetext, transform.position, transform.rotation);
            texts[i].transform.SetParent(tiles[i].transform, false);
            texts[i].GetComponent<Text>().text = varz[i];
            texts[i].transform.position += new Vector3(55*scaler, -4*scaler, 0);
        }
    }

    public static void test()
    {
        int i = 0;
        foreach(var item in abc)
        {
            foreach(var it in item)
            {
                i++;
            }
        }
        Debug.Log(i);
    }

    public static void IterateJtoken(JToken jtoken)
    {
        foreach (var value in jtoken)
        {
            foreach (JArray test in value)
            {
                for (int i = 0; i < test.Count; i++)
                {
                    foreach (var item in test[i])
                    {
                        var itemproperties = item.Parent;
                        foreach (JToken token in itemproperties)
                        {
                            if (token is JProperty)
                            {
                                var prop = token as JProperty;
                                //Console.WriteLine(prop.Name);           //PLC name
                                var plc = (JObject)prop.Value;
                                Dictionary<string, string> variables = new Dictionary<string, string>();
                                foreach (KeyValuePair<string, JToken> val in plc)
                                {

                                    if (val.Value is JObject)
                                    {
                                        JObject nestedobj = (JObject)val.Value;
                                        foreach (JProperty nestedvariables in nestedobj.Properties())
                                        {
                                            size++;
                                            var nestedVariableName = nestedvariables.Name;
                                            var nestedVariableValue = nestedvariables.Value;
                                            variables.Add(nestedVariableName, nestedVariableValue.ToString());
                                            //Console.WriteLine(nestedVariableName+" "+nestedVariableValue);
                                        }

                                    }
                                    else
                                    {
                                        size++;
                                        var variableName = val.Key;
                                        var variableValue = val.Value;
                                        variables.Add(variableName, variableValue.ToString());
                                        //Console.WriteLine(variableName+" "+variableValue);
                                    }

                                }
                                abc.Add(new Dictionary<string, string>(variables));
                            }
                        }
                    }
                }
            }


        }

    }
}

這是我附加到Unity3D中一個空游戲對象的腳本。 我還用面板孩子制作了一個畫布(寬:1090,高:430)。 我添加了一個網格布局組,其單元大小為100x100,間距為10x10。 畫布和面板將被拖到附加到空游戲對象的腳本上。 將它們拖到腳本后,您需要制作兩個預制件:

  • 100x100的UI /圖像,顏色為白色

  • UI /文本(160寬度,30高度)

創建完這兩個后,將它們拖到空游戲對象所附的腳本中。 現在,當啟動Unity3d應用程序時,您會看到一個畫布由JSON字符串中所有可用的PLC變量填充。

切換2個字符串以查看其在運行時動態變化(第一個字符串將添加10個元素,第二個字符串將添加20個元素)。

如果有任何清理代碼的建議,請告知。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM