Search code examples
c#jsondeserializationjson.net

How to deserialize object that can be an array or a dictionary with Newtonsoft?


I am using an API that returns a json object that I need to deserialize. My problem is that one of the members of those object is sometimes an empty array ("[]") and sometimes a dictionary ("{"1":{...}, "2":{...}}"). I want to deserialize it into either an array or a dictionary, since I don't car about the IDs, I just want a list of all the objects. Here is how I deserialize the object:

var response = JsonConvert.DeserializeObject<Response>(json);

And here is the definition of the Response class:

public class Response
{
    [JsonProperty(PropertyName = "variations")]
    public Dictionary<int, Variation> Variations { get; set; }
}

It works well when the Response contains a dictionary in it's variations field, but it fails when it contains an empty array. I'm getting an error from Newtonsoft saying that an array cannot be deserialized into a dictionary. If I define the Variations property as an array, it works for empty arrays, but it fails when it is a dictionary. What could I do to either deserialize correctly both possible values, or to ignore empty arrays and set Variations to null when it's an array instead of failing.

Thanks.


Solution

  • Here is the solution I used :

        public Dictionary<int, Variation> Variations
        {
            get
            {
                var json = this.VariationsJson.ToString();
                if (json.RemoveWhiteSpace() == EmptyJsonArray)
                {
                    return new Dictionary<int, Variation>();
                }
                else
                {
                    return JsonConvert.DeserializeObject<Dictionary<int, Variation>>(json);
                }
            }
        }
    
        [JsonProperty(PropertyName = "variations")]
        public object VariationsJson { get; set; }
    

    Basically, the variations are first deserialized in a basic object. When I want to read the value, I check if the object is an empty array, and if so I return an empty dictionary. If the object is a good dictionary, I deserialize it and return it.