简体   繁体   English

如何将Json中的自定义节点反序列化为名称不断变化的c#?

[英]How do I deserialize a custom node in Json to c#, whose name keeps changing?

Below is a section of json I receive from an endpoint. 以下是我从端点收到的json部分。

If you look at the Json below, 'User-Defined-Network-Name' is a custom node and the name will change each time. 如果您查看下面的Json,“用户定义的网络名称”是一个自定义节点,并且名称每次都会更改。

How do I define a C# object for this Json? 如何为此Json定义C#对象?

"addresses": {
            "public": [{
                "version": 6,
                "address": "2005:4600:788e:0910:1a72:81c0:ff03:c7y6"
            },
            {
                "version": 4,
                "address": "197.68.xx.xxx"
            }],
            "private": [{
                "version": 4,
                "address": "10.xx.xx.xxx"
            }],
            "User-Defined-Network-Name": [{
                "version": 4,
                "address": "192.xxx.x.xxx"
            }]
        }

This is how far I have come - 这就是我走了多远-

[Serializable]
    public class Addresses
    {
        public List<Public> @public { get; set; }
        public List<Private> @private { get; set; }
    }

Im using 'JavascriptSerializer' class to deserialize json. 我正在使用'JavascriptSerializer'类反序列化json。

Thanks, Ryan 谢谢,瑞安

addresses can be deserialized to a type like Dictionary<string,List<YourClass>> where YourClass holds version and addresss . 可以将addresses反序列化为Dictionary<string,List<YourClass>>类的类型Dictionary<string,List<YourClass>>其中YourClass保存versionaddresss

var obj = new JavaScriptSerializer().Deserialize<Root>(jsonstring);

-- -

public class Root
{
    public Dictionary<string,List<VersionAddress>> addresses;
    //Your other fields/properties
}

public class VersionAddress
{
    public string version;
    public string address;
}

You could take advantage of the dynamic nature of C#: 您可以利用C#的动态特性:

// this could come from user input:
string userDefinedName = "User-Defined-Network-Name";

string json = "YOUR JSON COMES HERE"; string json =“您的JSON即将出现”;

var serializer = new JavaScriptSerializer();
dynamic result = serializer.DeserializeObject(json);
int version = result["addresses"][userDefinedName][0]["version"];
string address = result["addresses"][userDefinedName][0]["address"];

Console.WriteLine(version);
Console.WriteLine(address);

and if you wanted to loop through the results: 如果您想遍历结果:

foreach (dynamic item in result["addresses"][userDefinedName])
{
    int version = item["version"];
    string address = item["address"];

    Console.WriteLine(version);
    Console.WriteLine(address);
}

Why don't you make network names a dictionary, with key of network name ? 为什么不使用网络名称关键字将网络名称设为字典? Then you can just iterate over it. 然后,您可以对其进行迭代。

I would not recommend using JavaScriptSerializer , as it has been deprecated. 我不建议使用JavaScriptSerializer ,因为它已被弃用。 If you want a third-party solution, JSON.Net is pretty good from what I hear. 如果您需要第三方解决方案,那么据我JSON.NetJSON.Net相当不错。

However, I'm one that's weird about dependencies, so I typically roll my own if it doesn't exist already. 但是,我对依赖项很奇怪,因此如果不存在依赖项,我通常会自己滚动。 Fortunately, this one isn't too hard due to DataContractJsonSerializer from the System.Runtime.Serialization namespace. 幸运的是,由于System.Runtime.Serialization命名空间中的DataContractJsonSerializer ,这System.Runtime.Serialization不太难。

All you need to do is first define all the objects in a nested fashion: 您需要做的就是首先以嵌套方式定义所有对象:

using System.Reflection;
using System.Runtime.Serialization;      // You will have to add a reference
using System.Runtime.Serialization.Json; // to System.Runtime.Serialization.dll

[DataContract]
public class AddressInfo
{ 
  [DataMember(Name = "address")]
  public string Address { get; set; }

  [DataMember(Name = "version")]
  public int Version { get; set; }
}

[DataContract]
public class AddressList
{ 
  [DataMember(Name = "public")]
  public IEnumerable<AddressInfo> Public { get; set; }

  [DataMember(Name = "private")]
  public IEnumerable<AddressInfo> Private { get; set; }

  [DataMember(Name = "User-Defined-Network-Name")]
  public IEnumerable<AddressInfo> UserDefined { get; set; }
}

Then a couple helper methods to do the deserialization: 然后使用几种辅助方法进行反序列化:

// This will change the DataMember.Name at runtime!
// This will only work if you know the node name in advance.
static void SetUserDefinedNodeName(string userDefinedNodeName)
{
  var type = typeof(AddressList);
  var property = type.GetProperty("UserDefined", BindingFlags.Default);
  var attribute = property.GetCustomAttribute<DataMemberAttribute>();

  if (attribute != null)
    attribute.Name = userDefinedNodeName;
}

static T Deserialize<T>(string jsonText, string userDefinedNodeName)
{
  SetUserDefinedNodeName(userDefinedName);

  var jsonBytes = Encoding.UTF8.GetBytes(jsonText);

  using (var stream = new MemoryStream(jsonBytes))
  {
    var serializer = new DataContractJsonSerializer(typeof(T));  
    var obj = serializer.ReadObject(stream) as T;

    return obj;
  }
}

Then you use it like so: 然后像这样使用它:

var jsonText = // get your json text somehow
var addressList = Deserialize<AddressList>(jsonText);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM