Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling JSON single object and array

I'm using Newtonsoft.Json to work with some JSON data that is being returned to me. Depending on what I request I can either get back something that looks like:

{
"TotalRecords":2,
"Result":
    [
        {
        "Id":24379,
        "AccountName":"foo"
        },
        {
        "Id":37209,
        "AccountName":"bar"
        }
    ],
"ResponseCode":0,
"Status":"OK",
"Error":"None"
}

or

{
    "Result":
    {
        "Id":24379,
        "AccountName":"foo"
    },
    "ResponseCode":0,
    "Status":"OK",
    "Error":"None"
}

So sometimes "Result" is an array of Results or "Result" could be a single response.

I've tried using the answer from How to handle both a single item and an array for the same property using JSON.net but I still get errors.

In particular I'm getting a

Newtonsoft.json.jsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List'...

Custom converter looks like:

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

        public override object ReadJson(JsonReader reader, Type objecType, 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();
        }
    }

My response class(es) look like

public class TestResponse
    {
        [JsonProperty("Result")]
        [JsonConverter(typeof(SingleOrArrayConverter<string>))]
        public List<DeserializedResult> Result { get; set; }
    }
public class DeserializedResult
    {
        public string Id { get; set; }
        public string AccountName { get; set; }
    }

And finally my request looks like

List<TestResponse> list = JsonConvert.DeserializeObject<List<TestResponse>>(response.Content);
like image 838
gilliduck Avatar asked May 21 '17 18:05

gilliduck


1 Answers

Your code is fine, it just needs a few type tweaks.

This line

List<TestResponse> list = JsonConvert.DeserializeObject<List<TestResponse>>(response.Content);

needs to be like this, because your response is an object, not a List.

TestResponse list = JsonConvert.DeserializeObject<TestResponse>(response);

Then your custom deserializer attribute:

[JsonConverter(typeof(SingleOrArrayConverter<string>))]

needs to become:

[JsonConverter(typeof(SingleOrArrayConverter<DeserializedResult>))]

because your Result object is not a string or an array of strings, it's either an array of DeserializedResults or a DeserializedResult.

like image 104
Maria Ines Parnisari Avatar answered Sep 19 '22 08:09

Maria Ines Parnisari