有没有办法使用C#从Winforms中的Json字符串动态创建属性?

时间:2019-03-25 19:16:32

标签: c# json

我们的应用程序中有一个方法可以将api对象模式返回为json。我试图找出是否仍然有拉出属性名称。例如,我收到以下json文本(反序列化后):

 "json": {
        "CompanyId": null,
        "Name": null,
        "UniqueIdentity": null,
        "AccountCode": null,
        "IsActive": null,
        "ContractNumber": null,
        "IsSiteCompany": null,
        "TaxCode": null,
        "GLCode": null,
        "CompanyTypeId": null,
        "AddressInfo": [
            {
                "AddressId": null,
                "CompanyId": null,
                "AddressTypeId": null,
                "Phone": null,
                "Fax": null,
                "Address": null,
                "Address2": null,
                "City": null,
                "State": null,
                "Zip": null,
                "Country": null
            }
        ],
        "ContactInfo": [
            {
                "ContactId": null,
                "CompanyId": null,
                "ContactTypeId": null,
                "FirstName": null,
                "MiddleName": null,
                "LastName": null,
                "Alias": null,
                "Position": null,
                "Email": null,
                "Phone": null,
                "IsPrimaryContact": null
            }
        ]

我需要提取诸如CompanyId,Name等的属性名称。我知道我可以创建一个类并将其反序列化为该类对象,问题是,我永远不知道架构将是什么。并非总是如此。我知道我可以一点一点地选择文本来提供属性名称,但是我想知道是否有人知道已经存在可以完成此任务的任何东西。

2 个答案:

答案 0 :(得分:2)

您正在查看JObject.Properties()。将您的JSON解析为JObject,然后遍历它。

示例代码:

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace JsonParse
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = @"{
                CPU: 'Intel',
                Drives: [
                    'DVD read/writer',
                    '500 gigabyte hard drive'
                ]
                }";
            JObject o = JObject.Parse(json);
            foreach (var prop in o.Properties())
            {
                Console.WriteLine(prop.Name);
            }
        }
    }
}

答案 1 :(得分:1)

您可以实现“访客”模式(类似于ExpressionVisitor):

public class JsonVisitor
{
    private readonly HashSet<string> uniqueProperties;
    private readonly List<string> allProperties;

    public JsonVisitor()
    {
        uniqueProperties = new HashSet<string>();
        allProperties = new List<string>();
    }

    public string UniqueProperties => string.Join(Environment.NewLine, uniqueProperties);
    public string AllProperties => string.Join(Environment.NewLine, allProperties);

    public void Visit(JObject jObject)
    {
        uniqueProperties.Clear();
        allProperties.Clear();

        VisitObject(jObject, "");
    }

    private void VisitObject(JObject jObject, string currentPath)
    {
        foreach (var property in jObject.Properties())
        {
            uniqueProperties.Add(property.Name);
            var path = $"{currentPath}/{property.Name}";
            allProperties.Add(path);

            VisitToken(property.Value, path);
        }
    }

    private void VisitArray(JArray jArray, string currentPath)
    {
        for (var i = 0; i < jArray.Count; ++i)
        {
            var item = jArray[i];
            var path = $"{currentPath}[{i}]";
            VisitToken(item, path);
        }
    }

    private void VisitToken(JToken token, string currentPath)
    {
        if (token is JObject childObject)
            VisitObject(childObject, currentPath);
        else if (token is JArray childArray)
            VisitArray(childArray, currentPath);

    }
}

用法:

var input = "{\r\n  \"json\":{\r\n    \"CompanyId\":null,\r\n    \"Name\":null,\r\n    \"UniqueIdentity\":null,\r\n    \"AccountCode\":null,\r\n    \"IsActive\":null,\r\n    \"ContractNumber\":null,\r\n    \"IsSiteCompany\":null,\r\n    \"TaxCode\":null,\r\n    \"GLCode\":null,\r\n    \"CompanyTypeId\":null,\r\n    \"AddressInfo\":[\r\n      {\r\n        \"AddressId\":null,\r\n        \"CompanyId\":null,\r\n        \"AddressTypeId\":null,\r\n        \"Phone\":null,\r\n        \"Fax\":null,\r\n        \"Address\":null,\r\n        \"Address2\":null,\r\n        \"City\":null,\r\n        \"State\":null,\r\n        \"Zip\":null,\r\n        \"Country\":null\r\n      }\r\n    ],\r\n    \"ContactInfo\":[\r\n      {\r\n        \"ContactId\":null,\r\n        \"CompanyId\":null,\r\n        \"ContactTypeId\":null,\r\n        \"FirstName\":null,\r\n        \"MiddleName\":null,\r\n        \"LastName\":null,\r\n        \"Alias\":null,\r\n        \"Position\":null,\r\n        \"Email\":null,\r\n        \"Phone\":null,\r\n        \"IsPrimaryContact\":null\r\n      }\r\n    ]\r\n  }\r\n}";
var json = JObject.Parse(input);

var visitor = new JsonVisitor();
visitor.Visit(json);

Console.WriteLine($"Unique properties:\r\n{visitor.UniqueProperties}");
Console.WriteLine();
Console.WriteLine($"All properties:\r\n{visitor.AllProperties}");

输出:

Unique properties:
json
CompanyId
Name
UniqueIdentity
AccountCode
// and so on

All properties:
/json
/json/CompanyId
/json/Name
/json/UniqueIdentity
/json/AccountCode
/json/IsActive
/json/ContractNumber
/json/IsSiteCompany
/json/TaxCode
/json/GLCode
/json/CompanyTypeId
/json/AddressInfo
/json/AddressInfo[0]/AddressId
/json/AddressInfo[0]/CompanyId
/json/AddressInfo[0]/AddressTypeId
/json/AddressInfo[0]/Phone
/json/AddressInfo[0]/Fax
// and so on