简体   繁体   English

使用 C# Json.NET 使用动态键反序列化 JSON

[英]Deserialize JSON with dynamic keys using C# Json.NET

From an external API I am receiving the below JSON response for the bank details of a customer.我从外部 API 收到以下有关客户银行详细信息的 JSON 响应。

{
   "bankDetails":[
      {
         "ABC Bank":[
            {
               "sNo":1,
               "acNo":"1235465",
               "acBalance":"100.25"
            },
            {
               "sNo":2,
               "acNo":"1235467",
               "acBalance":"50.25"
            }
         ],
         "bankName":"ABC Bank",
         "totalAmount":"150.50"
      },
      {
         "XYZ Bank":[
            {
               "sNo":1,
               "acNo":"1248565",
               "acBalance":"75.25"
            }
         ],
         "bankName":"XYZ Bank",
         "totalAmount":"75.25"
      },
      {
         "BCD Bank":[
            {
               "sNo":1,
               "acNo":"145665",
               "acBalance":"10.25"
            },
            {
               "sNo":2,
               "acNo":"195267",
               "acBalance":"5.25"
            }
         ],
         "bankName":"BCD Bank",
         "totalAmount":"15.50"
      }
   ]
}

I need to deserialize this to a C# class using JSON.Net.我需要使用 JSON.Net 将其反序列化为 C# 类。 What should be structure of the C# class as the first key is dynamic?. C# 类的结构应该是什么,因为第一个键是动态的? The first key with bank name returned will be different for each customer每个客户返回的带有银行名称的第一个密钥将不同

The typical solution to dealing with dynamic keys is to use a Dictionary<string, T> in place of a regular class.处理动态键的典型解决方案是使用Dictionary<string, T>代替常规类。 See How can I deserialize a child object with dynamic (numeric) key names?请参阅如何使用动态(数字)键名反序列化子对象? for an example of this.举个例子。 However, that solution doesn't really work for your case, because there are other properties in the same object which do not have dynamic keys (the bankName and totalAmount ), and the values of those properties are primitives whereas the value of dynamic property is an array of bank accounts.但是,该解决方案并不适合您的情况,因为同一对象中还有其他属性没有动态键( bankNametotalAmount ),并且这些属性的值是基元,而动态属性的值是一系列银行账户。 A better solution here is to use a JsonConverter .这里更好的解决方案是使用JsonConverter

Before we get to that, we need to set up a class structure to deserialize into.在我们开始之前,我们需要设置一个类结构来反序列化。 This is pretty straightforward:这非常简单:

class RootObject
{
    public List<Bank> BankDetails { get; set; }
}

[JsonConverter(typeof(BankConverter))]
class Bank
{
    public string BankName { get; set; }
    public decimal TotalAmount { get; set; }
    public List<Account> Accounts { get; set; }
}

class Account
{
    [JsonProperty("sNo")]
    public int SequenceNumber { get; set; }
    [JsonProperty("acNo")]
    public string AccountNumber { get; set; }
    [JsonProperty("acBalance")]
    public decimal Balance { get; set; }
}

You'll notice that I've added a few [JsonProperty] attributes in the Account class to map the shorthand property names in the JSON to friendlier property names in that class.您会注意到我在Account类中添加了一些[JsonProperty]属性,以将 JSON 中的速记属性名称映射到该类中更友好的属性名称。 And the [JsonConverter] attribute on the Bank class tells the serializer that we will be using a custom BankConverter to handle that class. Bank类上的[JsonConverter]属性告诉序列化器我们将使用自定义BankConverter来处理该类。

Here is the code for the BankConverter .这是BankConverter的代码。 It uses a JObject internally to make it easier to read and work with the JSON.它在内部使用JObject以使其更易于阅读和使用 JSON。

class BankConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Bank);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        Bank bank = new Bank();
        // populate the known properties (bankName and totalAmount)
        serializer.Populate(obj.CreateReader(), bank);
        // now handle the dynamic key
        bank.Accounts = obj[bank.BankName].ToObject<List<Account>>(serializer);
        return bank;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

With these classes in place, you can deserialize the JSON like this:有了这些类,您可以像这样反序列化 JSON:

var root = JsonConvert.DeserializeObject<RootObject>(json);

Here is a working demo: https://dotnetfiddle.net/knsRLv这是一个工作演示: https : //dotnetfiddle.net/knsRLv

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

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