无法将当前JSON对象反序列化为类型' WindowsService1 ...需要JSON数组(例如[1,2,3])才能正确反序列化

时间:2014-12-01 02:54:59

标签: c# json json.net arrays json-deserialization

我有一个Json对象如下:

{
"response" : {
  "method" : "switchvox.currentCalls.getList",
  "result" : {
     "current_calls" : {
        "current_call" : **[**
           {
              "provider" : "ThinkTel",
              "start_time" : "2014-11-30 02:24:52",
              "duration" : "5",
              "to_caller_id_number" : "800",
              "state" : "ivr",
              "from_caller_id_name" : "<unknown>",
              "to_caller_id_name" : "Main Answer Queue",
              "format" : "ulaw",
              "from_caller_id_number" : "9999999999",
              "id" : "SIP/1234567890-08682a00"
           },
           {
              "provider" : "ThinkTel",
              "start_time" : "2014-11-30 02:24:50",
              "duration" : "7",
              "to_caller_id_number" : "800",
              "state" : "ivr",
              "from_caller_id_name" : "<unknown>",
              "to_caller_id_name" : "Main Answer Queue",
              "format" : "ulaw",
              "from_caller_id_number" : "1111111111",
              "id" : "SIP/9876543210-08681350"
           }
        **]**,
        "total_items" : "2"
     }
  }
 }
}

我的课程是使用http://json2csharp.com

构建的

在我的

之前一切都很好
New Data allCalls = JsonConvert.DeserializeObject<Data>(json);

在数组中只获得1或0次调用(如果超过1,则全部工作)。 当只有1个调用和0个调用时,Json对象中的[]被删除,整个current_call块不存在。

以下是没有电话的情况:

 {
 "response" : {
  "method" : "switchvox.currentCalls.getList",
  "result" : {
     "current_calls" : {
        "total_items" : "0"
      }
    }
  }
}

这里只有一个电话看起来如何:

{
"response" : {
  "method" : "switchvox.currentCalls.getList",
  "result" : {
     "current_calls" : {
        "current_call" : {
           "provider" : "Internal",
           "start_time" : "2014-11-30 19:15:44",
           "duration" : "250",
           "to_caller_id_number" : "777",
           "state" : "talking",
           "from_caller_id_name" : "<unknown>",
           "to_caller_id_name" : "<unknown>",
           "format" : "ulaw->ulaw",
           "from_caller_id_number" : "231",
           "id" : "SIP/231-b4066e90"
        },
        "total_items" : "1"
   }
  }
 }
}

我收到以下错误:

无法将当前JSON对象(例如{“name”:“value”})反序列化为类型“WindowsService1.Service1 + CurrentCall []”,因为该类型需要JSON数组(例如[1,2,3])正确地反序列化。

要修复此错误,我需要将JSON更改为JSON数组(例如[1,2,3])或反序列化类型以成为正常的.NET类型(例如,不是像整数这样的基本类型,而不是集合类型像数组或List一样,可以从JSON对象反序列化。 JsonObjectAttribute也可以添加到类型中以强制它从JSON对象反序列化。

我理解错误意味着什么,但我现在不知道如何处理它。

1 个答案:

答案 0 :(得分:3)

由于current_call有时是一个对象,有时是一个数组,有时根本不存在,因此您需要使用JsonConverter以避免错误。您可以使用this similar question中的SingleOrArrayConverter<T>转换器并将其与空检查相结合,以获得可行的解决方案。这是一个涵盖所有三种场景的演示:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("--- array of calls ---");
        DeserializeAndDumpCallsList(@"
        {
            ""response"": {
                ""method"": ""switchvox.currentCalls.getList"",
                ""result"": {
                    ""current_calls"": {
                        ""current_call"": [
                            {
                                ""provider"": ""ThinkTel"",
                                ""start_time"": ""2014-11-30 02:24:52"",
                                ""duration"": ""5"",
                                ""to_caller_id_number"": ""800"",
                                ""state"": ""ivr"",
                                ""from_caller_id_name"": ""<unknown>"",
                                ""to_caller_id_name"": ""Main Answer Queue"",
                                ""format"": ""ulaw"",
                                ""from_caller_id_number"": ""9999999999"",
                                ""id"": ""SIP/1234567890-08682a00""
                            },
                            {
                                ""provider"": ""ThinkTel"",
                                ""start_time"": ""2014-11-30 02:24:50"",
                                ""duration"": ""7"",
                                ""to_caller_id_number"": ""800"",
                                ""state"": ""ivr"",
                                ""from_caller_id_name"": ""<unknown>"",
                                ""to_caller_id_name"": ""Main Answer Queue"",
                                ""format"": ""ulaw"",
                                ""from_caller_id_number"": ""1111111111"",
                                ""id"": ""SIP/9876543210-08681350""
                            }
                        ],
                        ""total_items"": ""2""
                    }
                }
            }
        }");

        Console.WriteLine("--- single call ---");
        DeserializeAndDumpCallsList(@"
        {
            ""response"": {
                ""method"": ""switchvox.currentCalls.getList"",
                ""result"": {
                    ""current_calls"": {
                        ""current_call"": {
                            ""provider"": ""Internal"",
                            ""start_time"": ""2014-11-30 19:15:44"",
                            ""duration"": ""250"",
                            ""to_caller_id_number"": ""777"",
                            ""state"": ""talking"",
                            ""from_caller_id_name"": ""<unknown>"",
                            ""to_caller_id_name"": ""<unknown>"",
                            ""format"": ""ulaw->ulaw"",
                            ""from_caller_id_number"": ""231"",
                            ""id"": ""SIP/231-b4066e90""
                        },
                        ""total_items"": ""1""
                    }
                }
            }
        }");

        Console.WriteLine("--- no current call ---");
        DeserializeAndDumpCallsList(@"
        {
            ""response"": {
                ""method"": ""switchvox.currentCalls.getList"",
                ""result"": {
                    ""current_calls"": {
                        ""total_items"": ""0""
                    }
                }
            }
        }");
    }

    private static void DeserializeAndDumpCallsList(string json)
    {
        var root = JsonConvert.DeserializeObject<RootObject>(json);
        List<CurrentCall> calls = root.response.result.current_calls.current_call;

        if (calls != null)
        {
            foreach (CurrentCall call in calls)
            {
                Console.WriteLine(call.from_caller_id_number);
            }
        }
        else
        {
            Console.WriteLine("no calls");
        }

        Console.WriteLine();
    }

    public class RootObject
    {
        public Response response { get; set; }
    }

    public class Response
    {
        public string method { get; set; }
        public Result result { get; set; }
    }

    public class Result
    {
        public CurrentCalls current_calls { get; set; }
    }

    public class CurrentCalls
    {
        [JsonConverter(typeof(SingleOrArrayConverter<CurrentCall>))]
        public List<CurrentCall> current_call { get; set; }
        public string total_items { get; set; }
    }

    public class CurrentCall
    {
        public string provider { get; set; }
        public string start_time { get; set; }
        public string duration { get; set; }
        public string to_caller_id_number { get; set; }
        public string state { get; set; }
        public string from_caller_id_name { get; set; }
        public string to_caller_id_name { get; set; }
        public string format { get; set; }
        public string from_caller_id_number { get; set; }
        public string id { get; set; }
    }

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

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken token = JToken.Load(reader);
            if (token.Type == JTokenType.Array)
            {
                return token.ToObject<List<T>>();
            }
            return new List<T> { token.ToObject<T>() };
        }

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

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

输出:

--- array of calls ---
9999999999
1111111111

--- single call ---
231

--- no current call ---
no calls