1

I am having trouble deserializing a json api. This is my api endpoint: https://www.googleapis.com/books/v1/volumes?q=harry+potter

The problem I have is: The JSON value could not be converted to System.Collections.Generic.IEnumerable at LineNumber: 0 | BytePositionInLine:1

failing at: Books = await JsonSerializer.DeserializeAsync<IEnumerable<Book>>(responseStream);

I think the reason is it is starting the parsing from the root, where it is receiving an object. Is there a way to skip the "kind" and "totalItems" node and start directly from the "items" node?

public async Task<IActionResult> Index()
    {
        var message = new HttpRequestMessage();
        message.Method = HttpMethod.Get;
        message.RequestUri = new Uri(URL);
        message.Headers.Add("Accept", "application/json");

        var client = _clientFactory.CreateClient();

        var response = await client.SendAsync(message);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await response.Content.ReadAsStreamAsync();
            Books = await JsonSerializer.DeserializeAsync<IEnumerable<Book>>(responseStream);
        }
        else
        {
            GetBooksError = true;
            Books = Array.Empty<Book>();
        }

        return View(Books);
    }

Model Class:

public class Book
{
    [Display(Name = "ID")]
    public string id { get; set; }
    [Display(Name = "Title")]
    public string title { get; set; }
    [Display(Name = "Authors")]
    public string[] authors { get; set; }
    [Display(Name = "Publisher")]
    public string publisher { get; set; }
    [Display(Name = "Published Date")]
    public string publishedDate { get; set; }
    [Display(Name = "Description")]
    public string description { get; set; }
    [Display(Name = "ISBN 10")]
    public string ISBN_10 { get; set; }
    [Display(Name = "Image")]
    public string smallThumbnail { get; set; }
}
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
DanCode
  • 525
  • 3
  • 7
  • 25
  • 1
    Your Book model still does not fit the structure of the item in the json. You can use some online json convert tools. – mj1313 Oct 30 '20 at 02:31

1 Answers1

2

I found a way to do this using JsonDocument. Its not very elegant because you are basically parsing the json twice but it should work.

var responseStream = await response.Content.ReadAsStreamAsync();

// Parse the result of the query to a JsonDocument
var document = JsonDocument.Parse(responseStream);

// Access the "items" collection in the JsonDocument
var booksElement = document.RootElement.GetProperty("items");

// Get the raw Json text of the collection and parse it to IEnumerable<Book> 
// The JsonSerializerOptions make sure to ignore case sensitivity
Books = JsonSerializer.Deserialize<IEnumerable<Book>>(booksElement.GetRawText(), new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

I used the answer to this question to create this solution.

Jay Fridge
  • 1,017
  • 11
  • 13