gpt4 book ai didi

c# - 解析数组和单个对象

转载 作者:行者123 更新时间:2023-12-05 08:45:57 27 4
gpt4 key购买 nike

API 重新调整了 json 对象,如下 2 种形式。

表格 1

{
"Pricing": [
{
"total": 27,
"currency": "USD",
"charges": [ //Chargers Array
{
"code": "C1",
"currency": "USD",
"rate": 15
},
{
"code": "C45",
"currency": "USD",
"rate": 12
}
]
}
]
}

表格 2

{
"Pricing": [
{
"total": 12,
"currency": "USD",
"charges": { //Chargers single object
"code": "C1",
"currency": "USD",
"rate": 12
}
}
]
}

如您所见,有时充电器对象会返回数组,有时则不会。我的问题是如何将其解析为 C# 类对象?如果我添加如下所示的 C# 类,则无法正确解析 Form 2。(正确解析 Form 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; }
}

使用 Newtonsoft 反序列化解析时发生错误。

MainObj obj = JsonConvert.DeserializeObject<MainObj>(json);

错误

Cannot deserialize the current JSON object (e.g. {"name":"value"})into type 'System.Collections.Generic.List`1[Charge]' because the typerequires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fixthis error either change the JSON to a JSON array (e.g. [1,2,3]) orchange the deserialized type so that it is a normal .NET type (e.g.not a primitive type like integer, not a collection type like an arrayor List) that can be deserialized from a JSON object.JsonObjectAttribute can also be added to the type to force it todeserialize from a JSON object. Path 'Pricing[0].charges.code', line1, position 69.

在使用 C# 接收不同类型的对象时,有什么常用的解析方法吗?

(我也查看了 this,但它是针对 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();
}
  • ReadJson 内首先我们得到一个JToken能够确定读取值的 Type (种类)
    • 基于此我们可以调用 ToObject<List<T>>ToObject<T>
  • CanConvert 内我们检查要填充的属性的类型是 List<T>
    • 即使有一个通用的 JsonConverter<T>您不必在其中定义 CanConvert , 它的 ReadJson可以用更复杂的方式实现
  • 由于问题是关于反序列化的,所以我还没有实现 WriteJson方法
    • 您也可以考虑覆盖 CanWrite基类的属性总是返回 false

有了我们手中的这个类(class),您可以用 JsonConverterAttribute 装饰您的属性(property)告诉 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; }

...
}

关于c# - 解析数组和单个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70859490/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com