Introduction
In this post we’ll begin with an overview of what an ISBN is. We’ll then talk about the website that will be the source for our data. It has two different web APIs (Application Programming Interface) that we can use. We’ll discuss one here, then in the next blog post cover the advanced version.
First though, if you haven’t read the introductory post in this series, The ArcaneBooks Project – An Introduction, I’d highly recommend doing so as it lays the foundation for why and how this project to get ISBN data originated.
ISBN Overview
ISBN, or International Standard Book Number, is a 10 or 13 digit number used to uniquely identify a book. You can find more information on ISBNs at https://www.isbn.org.
Every country has a service that creates an ISBN number for works created in that country, and cannot create numbers for books in other countries. ISBN’s began in 1970 as a ten digit number. In 2007, due to a dwindling supply of numbers, it was switched to a thirteen digit number.
Thirteen digit numbers in the US currently begin with 978-0 and 978-1, and 979-8. For purposes of this module, though, we will be able to use either the ten or thirteen number version of the ISBN.
Publishers sometimes vary the format through the inclusion or exclusion of dashes and/or spaces to separate the parts of the ISBN. For our purposes this won’t be relevant.
The data source we use (more on that momentarily) requires us to use only the number with no spaces or dashes. Thus the cmdlet in this module to fetch the ISBN data will remove any spaces or dashes from the number before it is used.
Converting Between Ten and Thirteen Characters
It is possible, although not necessary for this module, to convert the ten digit ISBN to a thirteen digit one. The https://www.isbn.org website has an online converter which you’ll find at https://www.isbn.org/ISBN_converter.
There is also a good blog article at The Postulate. In it the author gives an overview of how to convert from ten to thirteen character ISBNs, and provides code samples in Python.
Again, since our source can use either format of the ISBN, there are no plans at this time to implement the routine as PowerShell code.
Data Source – The Simple OpenLibrary API
In the ArcaneBooks PowerShell module that we are building, we will use the OpenLibrary.org API to get our data. The OpenLibrary website is run by the Internet Archive.
As I mentioned in the introduction, OpenLibrary actually has two different APIs we can call. The first I call the Simple API as it is very easy to use and parse the data.
The second API I’ve called the Advanced version, as it returns much more data, but the returned JSON is more complex to parse.
Note the words Simple and Advanced are my words to describe their APIs, not OpenLibrary’s. I just needed an easy way to distinguish between the two.
For our ArcaneBooks module we’ll be using the Advanced version as it contains extra data we need for our project. That may not be the case for you, so in this post I’ll cover how to use the Simple version. The next post will dive into the more complex Advanced API.
The OpenLibrary Simple API works in one of two ways. Whichever mode you choose, any dashes, spaces, etc must be removed before calling their URLs. Only a string of ten or thirteen numbers can be passed in.
In the first method, you can return an HTML webpage with the book data nicely formatted. The URL (Uniform Resource Locater, a fancy way of saying the web address) to access this is formatted like:
https://openlibrary.org/isbn/[isbn]
Where [isbn]
is replaced by the ten or thirteen character ISBN number.
https://openlibrary.org/isbn/0672218747
Will bring up the book data for William Orr’s The Radio Handbook.
We can also return the data in JSON format. To get the data in JSON, all we have to do is append .json
to the url. This url will return the same book in JSON format.
https://openlibrary.org/isbn/0672218747.json
The OpenLibrary is flexible, you can use either the ten or thirteen digit number in the call. Both of these examples will bring up the same book, Master Handbook of Ham Radio Circuits by Robert J. Traister.
https://openlibrary.org/isbn/0830678018.json
https://openlibrary.org/isbn/9780830678013.json
The Output JSON
Below is an example of the JSON output (formatted) as returned by the simple API when we call it using the call of https://openlibrary.org/isbn/0672218747.json
.
{
"publishers": [
"Sams"
],
"languages": [
{
"key": "/languages/eng"
}
],
"identifiers": {
"goodreads": [
"3084620"
],
"librarything": [
"1522789"
]
},
"title": "Radio Handbook",
"physical_format": "Hardcover",
"number_of_pages": 1168,
"isbn_13": [
"9780672218743"
],
"isbn_10": [
"0672218747"
],
"publish_date": "December 1982",
"key": "/books/OL7667922M",
"authors": [
{
"key": "/authors/OL1196498A"
}
],
"works": [
{
"key": "/works/OL8273120W"
}
],
"type": {
"key": "/type/edition"
},
"subjects": [
"Radio",
"Technology & Industrial Arts"
],
"latest_revision": 6,
"revision": 6,
"created": {
"type": "/type/datetime",
"value": "2008-04-29T15:03:11.581851"
},
"last_modified": {
"type": "/type/datetime",
"value": "2022-02-16T09:26:53.493088"
}
}
Parsing the Returned Data
Below is PowerShell code for accessing the data from OpenLibrary. We call the Simple API using Invoke-RestMethod
, then parse its various properties.
For an explanation of what is happening, see the comments in the PowerShell sample code. Note that the sample code doesn’t access every property returned, just enough of them to show you how to deal with the various ways the returned JSON is formatted.
# Set the URL and call the API via Invoke-RestMethod
# The returned JSON data will be held in the variable $BookData
$url = 'https://openlibrary.org/isbn/0672218747.json'
$bookData = Invoke-RestMethod $url
# Here is an extract of part of the JSON code.
# Below we'll show how to access it with PowerShell
<#
...more json here
"title": "Radio Handbook",
"number_of_pages": 1168,
...more json follows
#>
# Here we can just use the variable holding the returned JSON,
# then dot notation to access the property we want
# We're also using string interpolation. Because we are accessing
# properties of an object, we have to wrap it in $()
"Title: $($bookData.title)"
"Number Of Pages: $($bookData.number_of_pages)"
# Identifiers is a JSON object with two values, goodreads and librarything
<#
...more json here
"identifiers": {
"goodreads": [
"3084620"
],
"librarything": [
"1522789"
]
},
...more json follows
#>
# We can get the data by just using additional dot notation after the
# identifiers object
"GoodReads Number: $($bookData.identifiers.goodreads)"
"LibraryThing Number: $($bookData.identifiers.librarything)"
# Subjects is returned as a JSON array within the Subjects property
<#
...more json here
"subjects": [
"Radio",
"Technology & Industrial Arts"
],
...more json follows
#>
# You can deal with these in two ways.
# First, you can list individually
foreach ($s in $bookData.subjects)
{
"Subject: $s"
}
# In the second method you could combine in a single string
# Start by creating a StringBuilder object to append the strings
# as efficiently as possible
$mySubjects = [System.Text.StringBuilder]::new()
# Loop over the BookData Subjects array, copying the current
# subject into the variable $s
foreach ($s in $bookData.subjects)
{
if ($mySubjects.Length -gt 1)
{
# If we already have data in our StringBuilder $mySubjects,
# then add a comma first, then the name of the subject from $s
[void]$mySubjects.Append(", $($s)")
}
else
{
# If the length of our StringBuilder variable is less than 1,
# it's empty so we'll just append the name of the subject without
# a comma in front
[void]$mySubjects.Append($s)
}
}
# We need to convert the StringBuilder to a normal String to
# use it effectively, for example as a property in a class
$myCombinedSubjects = $mySubjects.ToString()
"Combined Subjects: $myCombinedSubjects"
# The created and last_modified properties are objects,
# simliar to the identifiers
<#
...more json here
"created": {
"type": "/type/datetime",
"value": "2008-04-29T15:03:11.581851"
},
"last_modified": {
"type": "/type/datetime",
"value": "2022-02-16T09:26:53.493088"
}
...more json follows
#>
# For both of these we only need the value property, so we can
# just ignore the type
"Created: $($bookData.created.value)"
"Last Modified: $($bookData.last_modified.value)"
Sample Data
Here are some sample ISBNs you can use for testing the sample code.
ISBN | Title |
---|---|
0-87259-481-5 | Your HF Digital Companion |
0-8306-7801-8 | Master Handbook of Ham Radio Circuits (Hardback) |
0-8306-6801-2 | Master Handbook of Ham Radio Circuits (Paperback) |
0-672-21874-7 | Radio Handbook Twenty-Second Edition |
0-07-830973-5 | Electricity Principles and Applications |
1418065803 | Delmar’s Standard Textbook of Electricity |
978-0-9890350-5-7 | The Antique Wireless Association Review Volume 31 |
1-887736-06-9 | Crystal Set Projects |
0-914126-02-4 | Vintage Radio |
See Also
For some of the techniques in this blog posts samples, I’ve written other posts in the past which cover their use.
To learn more about String Interpolation, see my post Fun With PowerShell Strings.
My post Fun With PowerShell Arrays will demonstrate how to work with arrays in PowerShell.
Conclusion
In this post we began with an overview of the ISBN, what it is and its history. We then dove into how to access the simple form of the OpenLibrary API to retrieve a books data based on the ISBN.
In my next post I will cover the use of OpenLibrary’s advanced API to get book data.
If you want to learn more about PowerShell, I have many courses on Pluralsight. Two courses in particular I would recommend are:
PowerShell 7 Quick Start for Developers on Linux, macOS, and Windows
Everyday PowerShell for Developers on Linux, macOS, and Windows