使用 C# Json.NET 使用动态密钥反序列化 JSON
Deserialize JSON with dynamic keys using C# Json.NET
来自外部 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"
}
]
}
我需要使用 JSON.Net 将其反序列化为 C# class。 C# class 的结构应该是什么,因为第一个键是动态的?。返回的第一个带有银行名称的密钥对于每个客户都是不同的
处理动态键的典型解决方案是使用 Dictionary<string, T>
代替常规 class。参见 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. A better solution here is to use a JsonConverter
。
在开始之前,我们需要设置一个 class 结构来反序列化。这非常简单:
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; }
}
您会注意到我在 Account
class 中添加了一些 [JsonProperty]
属性来映射 shorthand 属性 中的名称JSON 到 class 中更友好的 属性 名字。 Bank
class 上的 [JsonConverter]
属性告诉序列化程序我们将使用自定义 BankConverter
来处理 class.
这是 BankConverter
的代码。它在内部使用 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();
}
}
有了这些 classes,您可以像这样反序列化 JSON:
var root = JsonConvert.DeserializeObject<RootObject>(json);
这是一个工作演示:https://dotnetfiddle.net/knsRLv
来自外部 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"
}
]
}
我需要使用 JSON.Net 将其反序列化为 C# class。 C# class 的结构应该是什么,因为第一个键是动态的?。返回的第一个带有银行名称的密钥对于每个客户都是不同的
处理动态键的典型解决方案是使用 Dictionary<string, T>
代替常规 class。参见 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. A better solution here is to use a JsonConverter
。
在开始之前,我们需要设置一个 class 结构来反序列化。这非常简单:
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; }
}
您会注意到我在 Account
class 中添加了一些 [JsonProperty]
属性来映射 shorthand 属性 中的名称JSON 到 class 中更友好的 属性 名字。 Bank
class 上的 [JsonConverter]
属性告诉序列化程序我们将使用自定义 BankConverter
来处理 class.
这是 BankConverter
的代码。它在内部使用 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();
}
}
有了这些 classes,您可以像这样反序列化 JSON:
var root = JsonConvert.DeserializeObject<RootObject>(json);
这是一个工作演示:https://dotnetfiddle.net/knsRLv