blaataap
blaataap

Reputation: 229

Cannot deserialize the current JSON object with only one result

So I've seen this error message come by plenty. The problem im facing is that depanding on the result of my api i get this error or not. It happens when i only have 1 result(not sure what happens when there is no result at all). Im consuming an API and based on a search query it will give me a JSON result like this:

{
    "Cities": {
        "@size": "6",
        "City": [
            {
                "city": "Londern"
            },
            {
                "city": "Amsterdam"
            },
            {
                "city": "New York"
            },
            {
                "city": "Rome"
            },
            {
                "city": "Paris"
            },
            {
                "city": "Berlin"
            }
        ]
    }
}

My Classes look like this(simplified):

public class Cities
{
    public string size { get; set; }
    public List<City> City{ get; set; }
}
public class City
{
    public string City{ get; set; }
}
public class CitiesWrapper
{
    public Cities Cities { get; set; }
}

Now i have the following code to deserialise:

dynamic result = JsonConvert.DeserializeObject<CitiesWrapper>(await task.Content.ReadAsStringAsync());

This is where it goes wrong when the api gives me one result. What i've noticed is that the json result isnt an array anymore. It becomes like this:

{
    "Cities": {
        "@size": "1",
        "City": {
            "city": "Amsterdam area"
        }
    }
}

My question is what is best practise on how to tackle this?

Upvotes: 0

Views: 70

Answers (2)

blaataap
blaataap

Reputation: 229

So based on Darin's answer and some more digging i've came to an different approach. Im converting the Json object with: dynamic result = JsonConvert.DeserializeObject(json); after this i build in a check to see if its a JObject or JArray(if(result.Cities is JArray)). if its a array ill loop thru it and add items to a list if not ill take the value of the object.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1039160

You could use a JObject and depending on the size of the JSON deserialize to the correct type:

var parsedJson = JObject.Parse(json);
if (parsedJson["Cities"]["@size"].Value<string>() == "1")
{
    CityClass city = parsedJson["Cities"]["City"].ToObject<CityClass>();
}
else
{
    CityClass[] cities = parsedJson["Cities"]["City"].ToObject<CityClass[]>();
}

In this example I have used the following model:

public class CityClass
{
    public string City { get; set; }
}

Obviously this is an absolutely horrible way to handle JSON on the server side. When a property is defined as an array, the correct data type should be respected even if there's one element. So you should absolutely fix your API so that it is more consistent and it doesn't modify the City type depending on the result instead of doing hacks like this. It's an absolutely abominable way to design an API in such manner.

Upvotes: 1

Related Questions