dbpullman
dbpullman

Reputation: 79

How do deserialize an entire response that could be an array or a single object?

I have a situation where the response from an API can contain either an array or a single item. However, I'm struggling with the deserialization of the responses due to the array response containing another nested object. Here are the different responses that can be returned (sample).

This is the format of the response when a list of items is returned

{
  "data": {
    "items": [
       {
          "id": 1
       },
       {
          "id": 2
       }
    ]
  }
}

This is the response that gets sent when a single item is returned

{
  "data": {
    "id": 1
  }
}

My initial attempt to standardize the response included creating a custom converter attribute, but the issue there is you cannot pass a generic parameter into it. The code for the ReadJson is below:

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

    return new List<T>() { token.ToObject<T>() };
}

Here is the class that represents a response, but I'm getting the error that generics cannot be pass into attributes. After reading into it further, it seems as though this is by design.

public  class Response<T>
{
    [JsonProperty("version")]
    public string Version { get; set; }

    [JsonConverter(SingleOrArrayConverter<T>)]
    public T Data { get; set; }

    [JsonProperty("_links")]
    public Links Links { get; set; }
}

Anyone have any other thoughts/solutions to this problem?

Upvotes: 1

Views: 362

Answers (1)

Abhijith C R
Abhijith C R

Reputation: 1610

Have a few classes like below:

        public class Response
        {
            [JsonProperty("data")]
            public Data ResponseData { get; set; }
        }
        public class Data
        {
            [JsonProperty("id",NullValueHandling = NullValueHandling.Ignore)]
            public long? Id { get; set; }
            [JsonProperty("items", NullValueHandling = NullValueHandling.Ignore)]
            public List<Item> Items { get; set; }
        }
        public class Item
        {
            public long? Id { get; set; }
        }

Then Deserialize the response like below:

var responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Response>(responseString);

To further improve accessing the elements of data, include the below property to the Data class:

public List<Item> ResponseItems
            => Id != null
            ? new List<Item>(new Item[] { new Item { Id = Id} })
            : Items;

Upvotes: 1

Related Questions