Luca3317 / OpenLibrary.NET

C# library for OpenLibrary by the InternetArchive
MIT License
15 stars 3 forks source link

json deserialization error on LoadAsync #12

Closed bradyguyc closed 3 months ago

bradyguyc commented 3 months ago

OpenLibraryReadingLogs response = await OpenLibraryNET.Utility.OpenLibraryUtility.LoadAsync<OpenLibraryReadingLogs>(OLClient.BackingClient, ol_readbooks);
yields this error Error converting value {null} to type 'System.Int32'. Path 'reading_log_entries[3].work.cover_id', line 1, position 2581.

It looks like if coverid is null then it's through this error. Is there away around this?

https://openlibrary.org/people/bradyguy/books/already-read.json

with this json

{ "page": 1, "numFound": 173, "reading_log_entries": [ { "work": { "title": "Dune Messiah", "key": "/works/OL893526W", "author_keys": [ "/authors/OL79034A", "/authors/OL1846639A" ], "author_names": [ "Frank Herbert", "Michel Demuth" ], "first_publish_year": 1969, "lending_edition_s": "OL8865577M", "edition_key": [ "OL48591037M", "OL8865577M", "OL26719093M", "OL8889705M", "OL32200621M", "OL17489450M", "OL32663676M", "OL28914400M", "OL29328221M", "OL29887750M", "OL28639494M", "OL27292024M", "OL20042704M", "OL7470459M", "OL7501962M", "OL9537940M", "OL7502159M", "OL7501756M", "OL7502059M", "OL7525229M", "OL7501409M", "OL7973614M", "OL13362129M", "OL13276875M", "OL7877926M", "OL9041232M", "OL32216370M", "OL12543891M", "OL17721719M", "OL7501104M", "OL19824519M", "OL10256217M", "OL24235829M", "OL7500957M", "OL18143783M", "OL4571643M", "OL7500836M", "OL7569219M", "OL7500565M", "OL8536875M", "OL22645961M", "OL15049102M", "OL16181125M", "OL21405822M", "OL24057989M", "OL22078380M", "OL24205739M", "OL15048950M", "OL15048523M", "OL7569172M", "OL23744116M", "OL15048199M", "OL15068254M", "OL24226501M", "OL24248845M", "OL7501473M", "OL18715561M", "OL21657939M", "OL7501093M", "OL7501659M", "OL7500647M", "OL24764208M", "OL24669863M", "OL23044495M", "OL18263798M", "OL19610838M", "OL25432140M" ], "cover_id": 2421405, "cover_edition_key": "OL10256217M" }, "logged_edition": "/books/OL29887750M", "logged_date": "2024/02/24, 05:08:07" }, { "work": { "title": "Frank Herbert's Dune Saga 6-Book Boxed Set : Dune, Dune Messiah, Children of Dune, God Emperor of Dune, Heretics of Dune, and Chapterhouse", "key": "/works/OL22063570W", "author_keys": [ "/authors/OL79034A" ], "author_names": [ "Frank Herbert" ], "first_publish_year": 2020, "lending_edition_s": null, "edition_key": [ "OL30105507M" ], "cover_id": 10431756, "cover_edition_key": "OL30105507M" }, "logged_edition": "/books/OL30105507M", "logged_date": "2024/02/24, 05:08:07" }, { "work": { "title": "The Perfect Alibi", "key": "/works/OL34949670W", "author_keys": [ "/authors/OL7958834A" ], "author_names": [ "Blake Pierce" ], "first_publish_year": 2020, "lending_edition_s": null, "edition_key": [ "OL47310712M" ], "cover_id": 13775394, "cover_edition_key": "OL47310712M" }, "logged_edition": "/books/OL47310712M", "logged_date": "2024/02/24, 05:08:06" }, { "work": { "title": "The Perfect Affair (a Jessie Hunt Psychological Suspense-Book Seven)", "key": "/works/OL32944247W", "author_keys": [ "/authors/OL7958834A" ], "author_names": [ "Blake Pierce" ], "first_publish_year": 2020, "lending_edition_s": null, "edition_key": [ "OL44792984M" ], "cover_id": null, "cover_edition_key": null }, "logged_edition": "/books/OL44792984M", "logged_date": "2024/02/24, 05:08:06" }, { "work": { "title": "The Perfect House (a Jessie Hunt Psychological Suspense Thriller-Book Three)", "key": "/works/OL34606505W", "author_keys": [ "/authors/OL7958834A" ], "author_names": [ "Blake Pierce" ], "first_publish_year": 2019, "lending_edition_s": null, "edition_key": [ "OL46925349M" ], "cover_id": null, "cover_edition_key": null }, "logged_edition": "/books/OL46925349M", "logged_date": "2024/02/24, 05:08:06" }, { "work": { "title": "The Perfect Wife", "key": "/works/OL20869732W", "author_keys": [ "/authors/OL7958834A" ], "author_names": [ "Blake Pierce" ], "first_publish_year": 2018, "lending_edition_s": null, "edition_key": [ "OL31986300M", "OL28260318M" ], "cover_id": 10188946, "cover_edition_key": "OL28260318M" }, "logged_edition": "/books/OL28260318M", "logged_date": "2024/02/24, 05:08:06" }, { "work": { "title": "Star Wars - The Thrawn Trilogy - The Last Command", "key": "/works/OL83577W", "author_keys": [ "/authors/OL3315835A" ], "author_names": [ "Timothy Zahn" ], "first_publish_year": 1993, "lending_edition_s": null, "edition_key": [ "OL38350681M", "OL32526432M", "OL33843319M", "OL33959536M", "OL29501159M", "OL27727154M", "OL8889599M", "OL7826724M", "OL12611549M", "OL7850234M", "OL14411733M", "OL9035155M", "OL9035318M", "OL7829269M", "OL22445151M", "OL22627309M", "OL1738616M", "OL7543900M", "OL7914401M", "OL8102520M", "OL7827616M" ], "cover_id": 6529190, "cover_edition_key": "OL1738616M" }, "logged_edition": "/books/OL7829269M", "logged_date": "2024/02/24, 05:08:03" }, { "work": { "title": "Star Wars - Thrawn Trilogy - Dark Force Rising", "key": "/works/OL83573W", "author_keys": [ "/authors/OL3315835A" ], "author_names": [ "Timothy Zahn" ], "first_publish_year": 1992, "lending_edition_s": "OL32113240M", "edition_key": [ "OL38350777M", "OL32113240M", "OL33226140M", "OL33843320M", "OL33958846M", "OL26799482M", "OL29501158M", "OL24950688M", "OL7826723M", "OL9035306M", "OL9035154M", "OL12506888M", "OL7827567M", "OL9387948M", "OL12581331M", "OL7829010M", "OL24612237M", "OL8102519M", "OL7914400M", "OL7543899M", "OL7850251M", "OL7850057M", "OL1700409M", "OL23277163M" ], "cover_id": 538385, "cover_edition_key": "OL8102519M" }, "logged_edition": "/books/OL7829010M", "logged_date": "2024/02/24, 05:08:03" }, { "work": { "title": "Thrawn Trilogy Boxed Set", "key": "/works/OL26101671W", "author_keys": [ "/authors/OL3315835A" ], "author_names": [ "Timothy Zahn" ], "first_publish_year": 2022, "lending_edition_s": null, "edition_key": [ "OL38402015M", "OL35227518M" ], "cover_id": null, "cover_edition_key": null }, "logged_edition": "/books/OL35227518M", "logged_date": "2024/02/24, 05:08:03" }, { "work": { "title": "The end", "key": "/works/OL24850567W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL8058693A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Michael Kupperman" ], "first_publish_year": 2006, "lending_edition_s": null, "edition_key": [ "OL26463158M", "OL37365321M", "OL37372931M", "OL37380560M", "OL9231460M", "OL7276752M", "OL24277585M", "OL9246615M", "OL7279156M", "OL7279157M", "OL9233863M", "OL9233864M", "OL24930010M", "OL27284292M", "OL27351490M", "OL7291910M", "OL8406654M", "OL25935455M" ], "cover_id": 755390, "cover_edition_key": "OL8406654M" }, "logged_edition": "/books/OL27284292M", "logged_date": "2024/02/24, 05:08:02" }, { "work": { "title": "Penultimate Peril", "key": "/works/OL26500589W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL8058693A", "/authors/OL8591127A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Michael Kupperman", "Rose-Marie Vassallo-Villaneau" ], "first_publish_year": 2005, "lending_edition_s": "OL26465595M", "edition_key": [ "OL50642192M", "OL27002257M", "OL43337766M", "OL37191162M", "OL26465595M", "OL37365612M", "OL7276751M", "OL7291909M", "OL9231459M", "OL9246614M", "OL24278346M", "OL9233862M", "OL7279155M", "OL9233861M", "OL7279154M", "OL8483294M", "OL8406620M", "OL23086220M", "OL23274135M", "OL27351489M", "OL29550170M", "OL37354252M", "OL37345286M", "OL35830655M" ], "cover_id": 30661, "cover_edition_key": "OL9233861M" }, "logged_edition": "/books/OL29550170M", "logged_date": "2024/02/24, 05:08:02" }, { "work": { "title": "The Grim Grotto", "key": "/works/OL15104140W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL8058693A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Michael Kupperman" ], "first_publish_year": 2004, "lending_edition_s": null, "edition_key": [ "OL26465596M", "OL37361855M", "OL37373233M", "OL35770871M", "OL37347708M", "OL32774790M", "OL24768365M", "OL23272755M", "OL9310261M", "OL8483204M", "OL3293571M", "OL8406546M", "OL27351507M", "OL28289478M", "OL9246613M", "OL7279153M", "OL7279152M", "OL7291908M", "OL24279205M", "OL9233860M", "OL9233859M" ], "cover_id": 50569, "cover_edition_key": "OL7291908M" }, "logged_edition": "/books/OL8406546M", "logged_date": "2024/02/24, 05:08:01" }, { "work": { "title": "Slippery Slope", "key": "/works/OL27423194W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL3114807A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Rose-Marie Vassallo" ], "first_publish_year": 2003, "lending_edition_s": "OL26462403M", "edition_key": [ "OL26465592M", "OL26462403M", "OL24732743M", "OL24765719M", "OL7514882M", "OL7514933M", "OL23271086M", "OL24248794M", "OL3676111M", "OL7263185M", "OL9217900M", "OL8406494M", "OL25430109M", "OL25430110M", "OL25430111M", "OL9232236M", "OL7277528M", "OL9233467M", "OL7278759M", "OL27289952M", "OL27351501M", "OL27692722M", "OL37380820M", "OL37380819M", "OL37352586M", "OL37351036M" ], "cover_id": 8266470, "cover_edition_key": "OL3676111M" }, "logged_edition": "/books/OL7514882M", "logged_date": "2024/02/24, 05:08:01" }, { "work": { "title": "The Carnivorous Carnival", "key": "/works/OL15104132W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL8058693A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Michael Kupperman" ], "first_publish_year": 1708, "lending_edition_s": "OL26465594M", "edition_key": [ "OL26465594M", "OL12694920M", "OL37351382M", "OL37375846M", "OL37383554M", "OL28686673M", "OL7513772M", "OL23012698M", "OL3554426M", "OL23277262M", "OL24248447M", "OL24740203M", "OL9948797M", "OL8406448M", "OL7514073M", "OL27351122M", "OL28688325M", "OL28264225M", "OL31843973M", "OL29556493M", "OL8373896M", "OL9229466M", "OL7278826M", "OL7274757M", "OL9233534M" ], "cover_id": 6793899, "cover_edition_key": "OL24740203M" }, "logged_edition": "/books/OL3554426M", "logged_date": "2024/02/24, 05:08:01" }, { "work": { "title": "The Hostile Hospital", "key": "/works/OL15104028W", "author_keys": [ "/authors/OL20588A", "/authors/OL1514640A", "/authors/OL8058693A" ], "author_names": [ "Lemony Snicket", "Brett Helquist", "Michael Kupperman" ], "first_publish_year": 2001, "lending_edition_s": "OL7513136M", "edition_key": [ "OL45639418M", "OL43714830M", "OL26486984M", "OL37347707M", "OL37358004M", "OL37380818M", "OL7513212M", "OL7759946M", "OL7278823M", "OL9550077M", "OL7276685M", "OL9233531M", "OL9231393M", "OL23012807M", "OL24261678M", "OL23245855M", "OL23073391M", "OL3943351M", "OL27351118M", "OL28265372M", "OL30595963M", "OL29553546M", "OL7513136M", "OL12694918M", "OL8406415M"

JeCFe commented 3 months ago

@bradyguyc , you asked for a potential way to write a unit test to try this behaviour on #10 . Here is an example that can be used that is essential mocking out the client.SendAsync call in OpenLibraryUtility.RequestAsync

        [Fact]
        public async Task issue_12()
        {
            var mockMessageHandler = new Mock<HttpMessageHandler>();
            mockMessageHandler
                .Protected()
                .Setup<Task<HttpResponseMessage>>(
                    "SendAsync",
                    ItExpr.IsAny<HttpRequestMessage>(),
                    ItExpr.IsAny<CancellationToken>()
                )
                .ReturnsAsync(new HttpResponseMessage() { Content = new StringContent("1234") });

            var client = new HttpClient(mockMessageHandler.Object);

            var x = await OpenLibraryUtility.LoadAsync<string>(client, new Uri("/test"));
        }

I am unfamiliar with the implementation for the reading log stuff, so have only done a dummy implementation to prove out the mocking of the HTTP client call.

You will need to change the returnsAsync of the Setup to simulate the correct / error prone data to be returned. The error seems to occurring where the json deserialisation is being done in LoadAsync

f (string.IsNullOrWhiteSpace(path))
                return JsonConvert.DeserializeObject<T>(response);
            else
            {
                JToken token = JToken.Parse(response);
                return token[path]!.ToObject<T>();
            }

Edit: Tagged wrong person

bradyguyc commented 3 months ago

@JeCFe thanks i am not familiar with mock but will start the process of learning it....

bradyguyc commented 3 months ago

Rather than using LoadAsync I used the following and all works fine for loading MyBooks

OLMyBooksData myBooksData = await OLClient.MyBooks.GetCurrentlyReadingAsync(OLClient.Username); OLMyBooksData myBooksData1 = await OLClient.MyBooks.GetAlreadyReadAsync(OLClient.Username); OLMyBooksData myBooksData2 = await OLClient.MyBooks.GetWantToReadAsync(OLClient.Username);

Thus while this may still be an issue it's not critical in that I can obtain the data from the above methods.

Thanks Brady

Luca3317 commented 3 months ago

Without having had a look at you OpenLibraryReadingLogs class, I'd guess you alternatively could've fixed your issue by either making cover_id a nullable (i.e. int? cover_id) or make a custom JSONConverter for it that would convert null values into some other default integer value. Glad the builtin ReadingLogs API works for you though!

As an aside, if your OpenLibraryClient instance is logged in you dont have to pass in your username.