对具有不同数据结构的JSON进行反序列化

本文关键字:JSON 反序列化 数据结构 | 更新日期: 2023-09-27 18:21:10

我使用的JSON API之一返回响应,该响应根据从查询返回的结果数量而改变其数据结构。我从C#中使用它,并使用JSON.NET来反序列化响应。

以下是从API 返回的JSON

多结果响应:

{
  "response": {
    "result": {
      "Leads": {
        "row": [
          {
            "no": "1",
...
...
...

单一结果响应:

{
  "response": {
    "result": {
      "Leads": {
        "row": {
          "no": "1",
...
...
...

注意"行"节点的差异,在多个结果的情况下,它是一个数组,在单个结果的情况中是对象。

以下是我用来反序列化这个数据的类

类别:

public class ZohoLeadResponseRootJson
{
    public ZohoLeadResponseJson Response { get; set; }
}
public class ZohoLeadResponseJson
{
    public ZohoLeadResultJson Result { get; set; }
}
public class ZohoLeadResultJson
{
    public ZohoDataMultiRowJson Leads { get; set; }
}
public class ZohoDataMultiRowJson
{
    public List<ZohoDataRowJson> Row { get; set; }
}
public class ZohoDataRowJson
{
    public int No { get; set; }
    ...
}

"多结果响应"被反序列化而没有任何问题,但当响应中只有一个结果时,由于数据结构更改,无法反序列化响应。我得到一个异常

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON 
object (e.g. {"name":"value"}) into type 
'System.Collections.Generic.List`1[MyNamespace.ZohoDataRowJson]' 
because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) 
or change 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 array or List<T>) 
that can be deserialized from a JSON object. JsonObjectAttribute can also be 
added to the type to force it to deserialize from a JSON object.
Path 'response.result.Notes.row.no', line 1, position 44.

有没有一种方法可以在Json.Net中用一些属性来处理这个问题,并且希望不必编写转换器?

对具有不同数据结构的JSON进行反序列化

的灵感来自于一个类似问题的答案。

public class ZohoDataMultiRowJson
{
    [JsonConverter(typeof(ArrayOrObjectConverter<ZohoDataRowJson>))]
    public List<ZohoDataRowJson> Row { get; set; }
}
public class ArrayOrObjectConverter<T> : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize<List<T>>(reader);
        }
        else if (reader.TokenType == JsonToken.StartObject)
        {
            return new List<T>
            {
                (T) serializer.Deserialize<T>(reader)
            };
        }
        else
        {
            throw new NotSupportedException("Unexpected JSON to deserialize");
        }
    }
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}