[英]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.