2013-04-02 5 views
1

Я использую RestSharp, и у меня есть проблема, когда я десериализую Json.Как десериализовать json без знания формата?

В случае успеха, я получаю JSon подобное (данные таблицы):

{"status": "OK", "data": "[...]"} 

и в случае ошибки, я получаю Json как (данные строка):

{"status": "ERROR", "data": "..."} 

Как я могу узнать, нужно ли десериализовать Json таблицей или строкой?

Мой метод что-то подобное (она возвращает таблицу, но сбои, если Json возвращает строку в виде данных):

public Task<Items> GetItemById(string id) 
{ 
var client = 
new RestClient(string.Format("{0}/{1}/{2}/{3}/{4}", _baseUrl, 
    AppResources.RestApiVersion, userId, token, AppResources.NotUse)); 

var tcs = new TaskCompletionSource<Items>(); 
var request = new RestRequest(string.Format("/items/get/{0}", id)); 
client.ExecuteAsync<Items>(request, response => { 
    try 
    { 
     tcs.SetResult(new JsonDeserializer().Deserialize<Items>(response)); 
    } 
    catch (InvalidCastException e) 
    { 

    } 
}); 
return tcs.Task; 
} 

ответ

0

Я использую код из этого ответа: Deserialize JSON into C# dynamic object?

Это создает динамический объект в зависимости от содержимого объекта JSON. Мне нравится это совсем немного, хотя его код имеет несколько ошибок, которые я исправленные в моей версии ниже:

internal sealed class DynamicJsonConverter : JavaScriptConverter 
{ 
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     if (dictionary == null) 
      throw new ArgumentNullException("dictionary"); 

     return type == typeof(object) ? new DynamicJsonObject(dictionary) : null; 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); } 
    } 

    #region Nested type: DynamicJsonObject 

    private sealed class DynamicJsonObject : DynamicObject 
    { 
     private readonly IDictionary<string, object> _dictionary; 

     public DynamicJsonObject(IDictionary<string, object> dictionary) 
     { 
      if (dictionary == null) 
       throw new ArgumentNullException("dictionary"); 
      _dictionary = dictionary; 
     } 

     public override string ToString() 
     { 
      var sb = new StringBuilder(); 
      ToString(sb); 
      return sb.ToString(); 
     } 

     private void ToString(StringBuilder sb) 
     { 
      sb.Append("{"); 
      var firstInDictionary = true; 
      foreach (var pair in _dictionary) 
      { 
       if (!firstInDictionary) 
        sb.Append(","); 
       firstInDictionary = false; 
       var value = pair.Value; 
       var name = pair.Key; 
       if (value is string) 
       { 
        sb.AppendFormat("\"{0}\":\"{1}\"", name, value); 
       } 
       else if (value is IDictionary<string, object>) 
       { 
        sb.AppendFormat("\"{0}\":", name); 
        new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb); 
       } 
       else if (value is ArrayList) 
       { 
        sb.Append("\""); 
        sb.Append(name); 
        sb.Append("\":["); 
        var firstInArray = true; 
        foreach (var arrayValue in (ArrayList)value) 
        { 
         if (!firstInArray) 
          sb.Append(","); 
         firstInArray = false; 
         if (arrayValue is IDictionary<string, object>) 
          new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb); 
         else if (arrayValue is string) 
          sb.AppendFormat("\"{0}\"", arrayValue); 
         else 
          sb.AppendFormat("{0}", arrayValue); 

        } 
        sb.Append("]"); 
       } 
       else 
       { 
        sb.AppendFormat("\"{0}\":{1}", name, value); 
       } 
      } 
      sb.Append("}"); 
     } 

     public override bool TryGetMember(GetMemberBinder binder, out object result) 
     { 
      if (!_dictionary.TryGetValue(binder.Name, out result)) 
      { 
       // return null to avoid exception. caller can check for null this way... 
       result = null; 
       return true; 
      } 

      var dictionary = result as IDictionary<string, object>; 
      if (dictionary != null) 
      { 
       result = new DynamicJsonObject(dictionary); 
       return true; 
      } 

      var arrayList = result as ArrayList; 
      if (arrayList != null && arrayList.Count > 0) 
      { 
       if (arrayList[0] is IDictionary<string, object>) 
        result = new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x))); 
       else 
        result = new List<object>(arrayList.Cast<object>()); 
      } 

      return true; 
     } 
    } 

    #endregion 
} 

Остальная часть его кода примера применим.

+0

Ну, вы действительно не хотите просто десериализовать список. Чтобы десериализовать список, вам необходимо десериализовать содержимое списка, который будет представлять собой объекты со свойствами, отличными от списка. Я имею в виду, что если в основном объекте вы хотели только объекты списка, вы могли бы создать статическую «глубинную» переменную, которую вы увеличиваете в «ToString()» (она рекурсивна) и увеличивать глубину в начале «ToString()» и уменьшите его в конце и обрабатывайте только первый и второй операторы 'if' при глубине> 0. Третий, если (' else if (значение ArrayList) ') обрабатывает список. – Pete

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