Search code examples
c#apidictionaryflurl

Dictionaries and Flurl


I wish to access the "front_default" sprite in the PokeAPI for bulbasaur (https://pokeapi.co/).

I have the following collection initializer:

public class PokemonModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Dictionary<string, string> Sprites { get; set; }
}

And the following code for my WPF MainWindow:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async Task LoadImage(int pokedexNumber = 1)
    {
        PokedexProcess pkdx = new PokedexProcess();
        PokemonModel pkmn = await pkdx.LoadPokedex(pokedexNumber);
        var uriSource = new Uri(Convert.ToString(pkmn.sprites["front_default"]), UriKind.Absolute);
        pokemonImage.Source = new BitmapImage(uriSource);
    }

    private async void Window_Loaded(object sender, RoutedEventArgs e)
    {
        await LoadImage();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
    }
}

public class PokedexProcess
{
    public async Task<PokemonModel> LoadPokedex(int number)
    {
        var url = new Url($"https://pokeapi.co/api/v2/pokemon/{ number }");
        PokemonModel pkmn = await url.GetJsonAsync<PokemonModel>();
        return pkmn;

    }
}

However, when I try to access the sprite with this I get the following error message:

Flurl.Http.FlurlParsingException: 'Response could not be deserialized to JSON: GET https://pokeapi.co/api/v2/pokemon/1'

Inner Exception

JsonReaderException: Unexpected character encountered while parsing value: {. Path 'sprites.other', line 1, position 162133.

The only mistake I could think of is trying to access it the wrong way.

To access the specific sprite I need to access https://pokeapi.co/api/v2/pokemon/1 and then sprites->front_default->url of the image


Solution

  • You get the error, because your model expects all values in the sprites are keys with values for Dictionary. However, according to the payload the sprites field contains also objects.

    enter image description here

    The serializator can't deserialize sprites.other object to the Dictionary type. If you only need to get the front_default value from sprite, so try to define in your model only the value you need. Something like this.

    public class PokemonModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public SpritesModel Sprites { get; set; }
    }
    
    public class SpritesModel 
    {
        public string Front_Default { get; set; }
    }
    

    If you want to have more C#'s style property name for your SpritesModel, for example FrontDefault, you can do that with serialization attributes. More details you can find here