无法反序列化 Zoho Docs API 响应

Can't deserialize Zoho Docs API response

任何人都可以告诉我我在尝试反序列化此 Zoho Docs API 响应时做错了什么吗?

我有一个以“我的文件夹”为根的文件夹结构,然后是其中的“TestFolder”。这是我从 Zoho Docs API:

返回的 JSON 响应
[
    {
        "FOLDER_NAME": "My Folders",
        "SUCCESS": "1",
        "SCOPE": "0"
    },
    [
        {
            "AUTHOR_ID": "123456",
            "FOLDER_ID": "xxx",
            "PARENT_FOLDER_ID": "1",
            "FOLDER_NAME": "TestFolder",
            "LAST_MODIFIED_TIME": "1435875889219",
            "ENCFOLDER_NAME": "TestFolder",
            "SCOPE": "0",
            "AUTHOR_NAME": "John Smith",
            "LAST_MODIFIEDBY": "123456",
            "IS_SHARED": true,
            "LAST_MODIFIED_AUTHOR_NAME": "John Smith"
       }
    ]
]

我试图用这个 class 将响应反序列化到一个文件夹或列表中,但我没有成功:

    public class Folder
    {
        [JsonProperty("FOLDER_NAME")]
        public string FolderName { get; set; }
    }

无论我尝试将其反序列化为对象还是文件夹列表,我都会从 Json.NET:

收到此错误

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ZohoModels.Folder' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.

这里有两个问题:

  1. 根容器是数组而不是对象,因此需要反序列化为集合,例如List<Folder>

  2. 数组包含两个条目:一个 JSON 对象和嵌套的 JSON 数组。 documentation 含糊不清,但看起来这些文件夹是递归的,文件夹数组将包含成对的 folder/child 文件夹数组容器。由于 Json.NET 根据它是否实现 IEnumerable 来决定是否序列化一个 POCO,因此没有一个 class 可以同时从 JSON 数组和 JSON对象。因此,有必要为 List<Folder> 创建自定义 JSON 转换器以跳过数组并将文件夹与其子数组相匹配。

以下 classes 和转换器应该完成这项工作:

public class Folder
{
    public Folder() { this.Folders = new List<Folder>(); }

    [JsonProperty("FOLDER_NAME")]
    public string FolderName { get; set; }

    public List<Folder> Folders { get; set; }
}

public class FolderListConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<Folder>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        // Format of a folder list is
        // Object with name of folder
        // Array of child folders as a folderlist.
        var folders = (existingValue as List<Folder> ?? new List<Folder>());
        var array = JArray.Load(reader);
        foreach (var token in array)
        {
            switch (token.Type)
            {
                case JTokenType.Object:
                    folders.Add(token.ToObject<Folder>(serializer));
                    break;
                case JTokenType.Array:
                    {
                        var folder = folders.Last(); // Throws an exception if none read yet.
                        (folder.Folders = (folder.Folders ?? new List<Folder>())).AddRange(token.ToObject<List<Folder>>(serializer));
                    }
                    break;
                default:
                    throw new JsonSerializationException("unknown token " + token.ToString());
            }
        }
        return folders;
    }

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

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

并像这样使用它:

        var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new FolderListConverter() } };
        var folders = JsonConvert.DeserializeObject<List<Folder>>(json, settings);