Working with APIs and Parsing JSON Data in Golang: A Quickstart Reference Powered by RapidAPI and Hacker News

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Welcome back internet friend,

At the moment I’m currently doing a little hacking in Golang, and just wanted to post this quick little example of how to work with an api and parse json data in Go. Unlike some of the other languages I’ve worked with, in Golang you will need to create a struct to represent the JSON data you are receiving from the API endpoint you are hitting. That’s the trickiest part in my opinion. Also, the JSON data you will be working with is going to be an array of bytes, not a string. Last, you’ll use json.Unmarshal to parse your JSON and extract the information you are looking for.

Unfortunately, I don’t have time to write up a detailed post about how all of this works. However, I think the code snippet below is pretty cool and should provide a good reference if you happen to be playing around with APIs and JSON using Go. Note, the code below is using RapidAPI’s Hacker News endpoint to provide the JSON data. So if you’d like to try running this code yourself, make sure to visit rapidapi.com, register for an account, and replace the API key below with your own. Enjoy!

// REFERENCE (Parsing JSON in Golang): https://www.sohamkamani.com/blog/2017/10/18/parsing-json-in-golang/
// REFERENCE (Cast Int as String in Golang): https://yourbasic.org/golang/convert-int-to-string/
package main
import (
"fmt"
"net/http"
"io/ioutil"
"encoding/json"
"strconv"
)
type TopStories struct {
Story []int
}
type Story struct {
By string
Descendants int
Id int
Kids []int
Score int
Title string
Type string
URL string
}
func main() {
// ---------------------------------------------------------------------
// Hit the top stories endpoint for the Hacker News API
// via RapidAPI to get the story ids for the top stories
// today trending on Hacker News
// ---------------------------------------------------------------------
url := "https://community-hacker-news-v1.p.rapidapi.com/topstories.json?print=pretty"
// Create Request
request, _ := http.NewRequest("GET", url, nil)
request.Header.Add("x-rapidapi-host", "community-hacker-news-v1.p.rapidapi.com")
request.Header.Add("x-rapidapi-key", "YouR-SuPER-SWeeT-RaPiDaPi-KeY-GoeS-HeRe")
// Get Result, Result Body, and Result Body String
result, _ := http.DefaultClient.Do(request)
defer result.Body.Close()
resultBody, _ := ioutil.ReadAll(result.Body)
resultBodyStr := string(resultBody)
// Create an array to store our topStories,
// then append the story ids to our array
// using json.Unmarshall
var topStories []int
json.Unmarshal([]byte(resultBodyStr), &topStories)
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Next, Let's fetch some information about the top trending story on
// Hacker News. TODO: Fetch data for ALL the trending stories on HN
// ---------------------------------------------------------------------
var topStoryID string = strconv.Itoa(topStories[0])
url = "https://community-hacker-news-v1.p.rapidapi.com/item/" + topStoryID + ".json?print=pretty"
request, _ = http.NewRequest("GET", url, nil)
request.Header.Add("x-rapidapi-host", "community-hacker-news-v1.p.rapidapi.com")
request.Header.Add("x-rapidapi-key", "YouR-SuPER-SWeeT-RaPiDaPi-KeY-GoeS-HeRe")
result, _ = http.DefaultClient.Do(request)
defer result.Body.Close()
resultBody, _ = ioutil.ReadAll(result.Body)
resultBodyStr = string(resultBody)
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Now, let's parse the top story...
// ---------------------------------------------------------------------
var topStory Story
json.Unmarshal([]byte(resultBodyStr), &topStory)
fmt.Println("Top Story...")
fmt.Printf("Title: %s\n", topStory.Title)
fmt.Printf("URL: %s\n", topStory.URL)
// ---------------------------------------------------------------------
}
view raw hackernews.go hosted with ❤ by GitHub

UPDATE (1/27/2020): Remember to use a JSON to Golang Struct Conversion Tool such as JSON-to-Go to easily map Golang Structs to the JSON objects you want to decode. The code snippet below provides a good example of a struct created with JSON-to-Go:

package main
import (
"fmt"
"net/http"
"io/ioutil"
"encoding/json"
)
// Convert JSON to Go Struct
// https://mholt.github.io/json-to-go/
type SoccerMatch struct {
Title string `json:"title"`
Embed string `json:"embed"`
URL string `json:"url"`
Thumbnail string `json:"thumbnail"`
Date string `json:"date"`
Side1 struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"side1"`
Side2 struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"side2"`
Competition struct {
Name string `json:"name"`
ID int `json:"id"`
URL string `json:"url"`
} `json:"competition"`
Videos []struct {
Title string `json:"title"`
Embed string `json:"embed"`
} `json:"videos"`
}
func main() {
url := "https://free-football-soccer-videos1.p.rapidapi.com/v1/"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-rapidapi-host", "free-football-soccer-videos1.p.rapidapi.com")
req.Header.Add("x-rapidapi-key", "YouR-SuPeR-SWeeT-aPi-KeY-GoeS-HeRe")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
bodyStr := string(body)
var matches []SoccerMatch
json.Unmarshal([]byte(bodyStr), &matches)
for i := 0; i < len(matches); i++ {
fmt.Println(matches[i].Title)
}
}
view raw ApiExample.go hosted with ❤ by GitHub
 

topherPedersen