Search code examples
c#jsonasp.net-coreblazor-webassemblyjson-deserialization

How to model a target class for receiving a JSON HTML response in .NET 5


I'm trying to read a list of objects from a public web API that provides a JSON file with an array of objects, I'm using Blazor and the .NET 5 platform.

The de-serialization fails with this error:

System.Text.Json.JsonException: The JSON value could not be converted to Meme[].

I suspect I'm modeling the "receiving" object incorrectly, should I change my code or use other libraries for this code to succeed?

The API can be found at this endpoint. I tried reading the response in these two ways:

var response = await Http.GetFromJsonAsync<Meme[]>("https://api.imgflip.com/get_memes");

and

var httpResponse = await Http.GetAsync("https://api.imgflip.com/get_memes");
var response = await httpResponse.Content.ReadFromJsonAsync<Meme[]>();

the Meme class is declared as such:

public string Id { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int BoxCount { get; set; }

and the response should contain this content:

"success": true,
"data": {
    "memes": [
        {
            "id": "181913649",
            "name": "Drake Hotline Bling",
            "url": "https://i.imgflip.com/30b1gx.jpg",
            "width": 1200,
            "height": 1200,
            "box_count": 2
        },
        {
            ...
        },
        ... 
    ]
}

These are the libraries I'm including:

using System.Net.Http;
using System.Net.Http.Json;

Solution

  • The response includes more than your Memes itself. The Meme array is within the object data and memes. Model the entire response and you will be able to deserialize it. So you will need the following:

    public class Response
    {
        public bool success { get; set; }
        public Data data { get; set; }
    }
    
    public class Data
    {
        public Meme[] memes { get; set; }
    }
    
    public class Meme
    {
        public string id { get; set; }
        public string name { get; set; }
        public string url { get; set; }
        public int width { get; set; }
        public int height { get; set; }
        public int box_count { get; set; }
    }
    

    Now you can use that class like this:

    var response = await httpResponse.Content.ReadFromJsonAsync<Response>();
    

    Note that there is a handy tool in Visual Studio that will generate your JSON classes for you (I used it here). You can paste JSON as classes under Edit > Paste Special > Paste JSON as Classes. You can still use "normal" camel casing, but you may have to instruct the serializer to do not match property names case-sensitive.