C# Corner
Tech
News
Videos
Forums
Jobs
Books
Events
More
Interviews
Live
Learn
Training
Career
Members
Blogs
Challenges
Certification
Contribute
Article
Blog
Video
Ebook
Interview Question
Collapse
Feed
Dashboard
Wallet
Learn
Achievements
Network
Refer
Rewards
SharpGPT
Premium
Contribute
Article
Blog
Video
Ebook
Interview Question
Register
Login
Querying Last.fm Web API With F#
WhatsApp
Bohdan Stupak
7y
9.2
k
0
3
25
Blog
Introduction
This blog shows how to query top 50 most listened musicians of last.fm users with F#. The complete source code which sheds more light on function composition, unit testing, property-based testing and railway-oriented programming can be accessed on
GitHub
.
Setting up type providers
Type providers
is a useful F# feature that allows strongly-type responses from REST APIs, CSV files, and HTML tables etc. and thus, is useful for REST APIs interaction, data analysis tasks, and much more.
To enable type providers in our project, we perform the following steps.
Import FSharp.Data
Provide snippet of API response.
let [<Literal>] TopArtistsSample =
""
"{
"topartists"
:{
"artist"
:[
{
"name"
:
"Porcupine Tree"
,
//skipped for the sake of breivety
}
],
"@attr"
:{
"user"
:
"Morbid_soul"
,
"page"
:
"1"
,
"perPage"
:
"2"
,
"totalPages"
:
"165"
,
"total"
:
"330"
}
}
}
""
"
Create type from the sample above.
type TopArtists = JsonProvider<TopArtistsSample>
Querying the API
Now, let us define some constants.
[<Literal>]
let userName =
"<login here>"
[<Literal>]
let apiKey =
"<api key here>"
[<Literal>]
let baseUrl =
"http://ws.audioscrobbler.com"
[<Literal>]
let getTopArtistsPattern =
"{0}/2.0/?method=user.gettopartists&user={1}&api_key={2}&period=12month&format=json"
With these constants, we can construct URL for API call, as shown below.
let path = String.Format(getTopArtistsPattern, baseUrl, userName, apiKey)
We cast a response to our type defined in "Type providers" section.
TopArtists.Parse(text)
The complete function call looks like this.
let getTopArtists =
let path = String.Format(getTopArtistsPattern, baseUrl, userName, apiKey)
let data = Http.Request(path)
match data.Body with
| Text text -> TopArtists.Parse(text).Topartists.Artist
| _ ->
null
Handling errors
You may have noticed that we didn't handle any possible exceptions when performing the call. To do this, we will wrap our result type inside the monadic type which indicates whether the function executed successfully or not.
type Result<
'TSuccess,'
TFailure> =
| Success of 'TSuccess
| Failure of 'TFailure
This can be useful to
chain functions in order to handle errors gracefully
.
Now, our final function makes use of declared type, as shown below.
let getTopArtists () =
try
let path = String.Format(getTopArtistsPattern, baseUrl, userName, apiKey)
let data = Http.Request(path)
match data.Body with
| Text text -> Success(TopArtists.Parse(text).Topartists.Artist)
| _ -> Failure
"getTopArtists. Unexpected format of reponse message"
with
| ex -> Failure ex.Message
Last.fm
Web API With F#
F#
People also reading
Membership not found