无法反序列化Zoho Docs API响应

时间:2015-08-13 13:51:26

标签: c# json serialization json.net zoho

任何人都可以告诉我在尝试反序列化此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"
       }
    ]
]

我已经尝试使用此课程将响应反序列化为文件夹或列表,但我没有运气:

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

我是否尝试将其反序列化为对象或文件夹列表我从Json.NET得到此错误:

  

无法将当前的JSON数组(例如[1,2,3])反序列化为类型' ZohoModels.Folder'因为该类型需要一个JSON对象(例如{" name":" value"})才能正确反序列化。

     

要修复此错误,请将JSON更改为JSON对象(例如{" name":" value"})或将反序列化类型更改为数组或实现的类型像List这样的集合接口(例如ICollection,IList)可以从JSON数组反序列化。 JsonArrayAttribute也可以添加到类型中,以强制它从JSON数组反序列化。

1 个答案:

答案 0 :(得分:1)

这里有两个问题:

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

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

  3. 以下类和转换器应该完成这项工作:

    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);