1

I am working on a WPF MVVM application to retrieve some cryptocurrency information from this API. I am able to call the API and get an HTTP response, however, I am having trouble deserializing this response to an object. I understand that the symbol variable is passed but not used, however, I want the deserialization process to work and then I will format the URI accordingly to include the symbol and the API Key. Here is the code:

Crypto Object

public class Crypto
{
    public string? Symbol { get; set; }
    public string? Name { get; set; }
    public double? Price { get; set; }
    public double? ChangesPercentage { get; set; }
}

API Call Service Interface

public interface ICryptoService
{
    Task<Crypto> GetCrypto(string symbol); 
}

API Call Service

public async Task<Crypto> GetCrypto(string symbol)
    {
        using (HttpClient client = new HttpClient())
        {
            using var response = await client.GetAsync("https://financialmodelingprep.com/api/v3/quote/BTCUSD?apikey=KEY", HttpCompletionOption.ResponseHeadersRead);

            response.EnsureSuccessStatusCode();

            if (response.Content is object && response.Content.Headers.ContentType.MediaType == "application/json")
            {
                var responseStream = await response.Content.ReadAsStreamAsync();

                try
                {
                    return await System.Text.Json.JsonSerializer.DeserializeAsync<Crypto>(responseStream, new System.Text.Json.JsonSerializerOptions { IgnoreNullValues = true, PropertyNameCaseInsensitive = true });
                }
                catch (JsonException)
                {
                    Console.WriteLine("Invalid JSON!");
                }
            }
            else
            {
                Console.WriteLine("HTTP Response cannot be deserialised");
            }

            return null;
        }
    }
}

Main Method

        CryptoService cryptoService = new CryptoService();

        cryptoService.GetCrypto("BTCUSD").ContinueWith((task) =>
        {
            var crypto = task.Result;
        });

I am attaching the JSON response that the link will provide below:

[
 {
"symbol": "BTCUSD",
"name": "Bitcoin USD",
"price": 22887.08,
"changesPercentage": -0.1263,
"change": -28.9473,
"dayLow": 22887.08,
"dayHigh": 23351.51,
"yearHigh": 48086.836,
"yearLow": 15599.047,
"marketCap": 441375461059,
"priceAvg50": 19835.04,
"priceAvg200": 19730.518,
"volume": 27292504064,
"avgVolume": 23965132574,
"exchange": "CRYPTO",
"open": 23267.4,
"previousClose": 23267.4,
"eps": null,
"pe": null,
"earningsAnnouncement": null,
"sharesOutstanding": 19284918,
"timestamp": 1675872360
 }
]

This is the exception that I get whenever I run the code:

Exception thrown: 'System.Text.Json.JsonException' in System.Private.CoreLib.dll
dbc
  • 104,963
  • 20
  • 228
  • 340
  • 3
    The JSON you've got doesn't represent a `Crypto` object; it represents an *array* (or list) of objects. Try deserializing to a `List`. Also, regardless of whether or not that works, you should edit your question to show the *full* exception, not just the type of it. – Jon Skeet Feb 08 '23 at 18:34
  • 1
    Isn't `IgnoreNullValues` obsolete? – Jimi Feb 08 '23 at 18:42

1 Answers1

1

Your json is a json array, not a single json object, so you need to deserialize to a collection:

var result = await JsonSerializer.DeserializeAsync<List<Crypto>>(...);

P.S.

In general case it is recommended to just await async functions instead of using ContinueWith.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132