wee*_*raa 2 c# parsing json json.net
API 返回 json 对象,如下所示 2 种形式。
表1
{
"Pricing": [
{
"total": 27,
"currency": "USD",
"charges": [ //Chargers Array
{
"code": "C1",
"currency": "USD",
"rate": 15
},
{
"code": "C45",
"currency": "USD",
"rate": 12
}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
表2
{
"Pricing": [
{
"total": 12,
"currency": "USD",
"charges": { //Chargers single object
"code": "C1",
"currency": "USD",
"rate": 12
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,充电器对象有时会返回数组,有时则不会。我的问题是如何将其解析为 C# 类对象?如果我添加如下所示的 C# 类,则无法正确解析表单 2。(正确解析表单 1)
public class Charge
{
public string code { get; set; }
public string currency { get; set; }
public decimal rate { get; set; }
}
public class Pricing
{
public decimal total { get; set; }
public string currency { get; set; }
public List<Charge> charges { get; set; } //In Form 2, this should be single object
}
public class MainObj
{
public List<Pricing> Pricing { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
使用Newtonsoft反序列化解析时发生错误。
MainObj obj = JsonConvert.DeserializeObject<MainObj>(json);
Run Code Online (Sandbox Code Playgroud)
错误
无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型 'System.Collections.Generic.List`1[Charge]',因为该类型需要 JSON 数组(例如 [1,2,3] )以正确反序列化。要修复此错误,请将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改反序列化类型,使其成为普通的 .NET 类型(例如,不是像整数这样的原始类型,不是像这样的集合类型)数组或列表),可以从 JSON 对象反序列化。还可以将 JsonObjectAttribute 添加到类型中以强制其从 JSON 对象反序列化。路径“Pricing[0].charges.code”,第 1 行,位置 69。
使用 C# 接收不同类型的对象类型时,有什么通用的解析方法吗?
(我也研究了这个,但它是针对 java 的。大多数此类问题是针对 java 而不是 C# 提出的。)
处理这个问题的另一种方法是定义一个JsonConverter可以处理这两种情况的自定义。
class ArrayOrObjectConverter<T> : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
return token.Type == JTokenType.Array
? token.ToObject<List<T>>()
: new List<T> { token.ToObject<T>() };
}
public override bool CanConvert(Type objectType)
=> objectType == typeof(List<T>);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
=>throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
ReadJson我们得到一个JToken能够确定读取值的Type(种类)
ToObject<List<T>>或ToObject<T>CanConvert我们检查要填充的属性的类型是List<T>
JsonConverter<T>您不必定义的泛型CanConvert,它也ReadJson可以以更复杂的方式实现WriteJson方法
CanWrite基类的属性以始终返回false有了这个类,您可以用 a 来装饰您的属性,JsonConverterAttribute告诉 Json.NET 如何处理这些属性
public class Pricing
{
public decimal total { get; set; }
public string currency { get; set; }
[JsonConverter(typeof(ArrayOrObjectConverter<Charge>))]
public List<Charge> charges { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)