2014-12-01 3 views
1

я объект JSON следующим образом:Не может десериализации текущего объекта JSON в тип «WindowsService1 ... требует массива JSON (например, [1,2,3]) для десериализации правильно

{ 
"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/-08681350" 
      } 
     **]**, 
     "total_items" : "2" 
    } 
    } 
} 
} 

Моих классов были построены с использованием http://json2csharp.com

все хорошо, пока мой

New Data allCalls = JsonConvert.DeserializeObject<Data>(json); 

получает только 1 или 0, вызов в массиве (если есть больше чем 1, то все работает). [] в объектах Json удаляются, когда есть только 1 вызов и 0 вызовов, весь блок current_call отсутствует.

Вот как это выглядит без звонков:

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

А вот как это выглядит только 1 звонок:

{ 
"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 (например, не примитивным типом типа integer, а не набором типа массива или списка), которые можно десериализовать из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализовать объект JSON.

Я понимаю, что означает ошибка, но я не сейчас, как подойти к нему в моей ситуации.

+1

Поскольку 'current_call' иногда объект, а иногда массив, вам нужно будет использовать' JsonConverter' справиться с этим , См. [Как обрабатывать как отдельный элемент, так и массив для одного и того же свойства с помощью JSON.net] (http://stackoverflow.com/q/18994685/10263). В принятом ответе есть класс «SingleOrArrayConverter », который должен быть можно использовать здесь. –

+0

@BrianRogers Ты только что сделал мой вечер! Огромное спасибо. Моя единственная проблема заключается в том, как она иногда обрабатывает ситуацию с объектом? – TarasBulba

+0

Он обрабатывает оба, то есть точку. Вы объявляете свой класс иметь свойство списка, а если JSON имеет один объект, вы получите список с одним элементом вместо ошибки. Если у JSON есть массив, вы все равно получаете список (с несколькими элементами). –

ответ

3

С current_call иногда является объектом, иногда массивом, а иногда и вовсе нет, вам нужно использовать JsonConverter во избежание ошибок. Вы можете использовать конвертер от this similar question и объединить его с нулевой проверкой, чтобы получить работоспособное решение. Вот демо, которое охватывает все три сценария:

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/-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 
Смежные вопросы

 Смежные вопросы