1

I use RestSharp and I have a problem when I deserialize a Json.

In case of success, I receive a Json like that (data is a table):

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

and in case of error, I receive a Json like (data is a string):

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

How can I know if I have to deserialize the Json with a table or with a string?

My method is something like that (it returns a table but crashes if the Json returns a string as data) :

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;
}
user2169047
  • 77
  • 2
  • 12

1 Answers1

0

I use code from this answer: Deserialize JSON into C# dynamic object?

It generates a dynamic object depending on the content of the JSON object. I like it quite a bit, though his code has several bugs that I have fixed in my version below:

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
}

The rest of his code example is applicable.

Community
  • 1
  • 1
Pete
  • 6,585
  • 5
  • 43
  • 69
  • Well, you don't really want to just deserialize the list, though. To deserialize the list, you have to deserialize the content of the list, which will be objects with non-list properties. I mean, if in the main object you only wanted the list objects, you could create a static "depth" variable that you increment in `ToString()` (it's recursive) and increment depth at the beginning of `ToString()` and decrement it at the end and only handle the first and second `if` statements when depth > 0. The third if (`else if (value is ArrayList)`) handles the list. – Pete Nov 01 '13 at 18:13