在我遇到很多麻烦的那一刻,我正在进行的项目。我从外部源获取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反序列化器。我将在我正在进行作业的应用程序中使用它。在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中可视化它们。
答案 0 :(得分:1)
尝试将两个数组项转换为列表,这样就可以了。我遇到了同样的问题,并且解决了同样的问题。试试,如果它不起作用,请告诉我。我会和你分享代码。
答案 1 :(得分:1)
您可以使用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);
}
您可以轻松枚举 root 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);
答案 2 :(得分:1)
我想我理解你的问题。如果您无法定义可用于将JSON映射到C#的C#类,那么您需要重新考虑它。为什么不创建一个只有Dictionary<string,string>
或HashSet<string,string>
如果您正在设计如何构建PLC的有效负载,那么您可以使其适合具有一些基本属性的简单C#类和不一致创建/可用的变量的字典。
或者如果您想要dynamic
类型行为,https://weblog.west-wind.com/posts/2012/Aug/30/Using-JSONNET-for-dynamic-JSON-parsing
答案 3 :(得分:1)
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
}
答案 4 :(得分:1)
您可以使用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]);
}
}
答案 5 :(得分:0)
设法解决了我的问题!你们共享过时的信息,并编写了大量的代码。但是,嘿,它有效: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 /文本(160宽度,30高度)
创建完这两个后,将它们拖到空游戏对象附带的脚本中。 现在,当启动Unity3d应用程序时,您会看到一个画布由JSON字符串中所有可用的PLC变量填充。
切换2个字符串以查看其在运行时动态变化(第一个字符串将添加10个元素,第二个字符串将添加20个元素)。
如果有任何清理代码的建议,请告知。