Problem I'm new to Go and I'm trying to store json data in a struct from the Gov.uk public holidays API, so I can use this later on in my frontend.
If I run
var sb = string(body)
fmt.Println(sb)
I can see the data that's being returned in my terminal. I know that the response body is made up of bytes and the above converts it to a string.
I would like to iterate through the response body and store the data in a slice of structs called holidays
, each struct will contain the data for a single public holiday. For some reason, the holidays variable returns an empty slice: []
.
I guess my two questions are:
- What's the best way to transform json data into a slice of structs to be used later on?
- Why does the holidays variable return an empty slice?
Thanks!
Here's my code below: package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type Response struct {
Data []Data
}
type Data struct {
Division string
Bankholiday Bankholiday
}
type Bankholiday struct {
Title string
Date string
}
func main() {
resp, err := http.Get("https://www.gov.uk/bank-holidays.json")
if err != nil {
log.Fatal(err)
}
if resp.Body != nil {
defer resp.Body.Close()
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
var response Response
json.Unmarshal(body, &response)
var holidays = []Bankholiday{}
for _, date := range response.Data {
holidays = append(holidays, Bankholiday{
Title: date.Bankholiday.Title,
Date: date.Bankholiday.Date,
})
}
fmt.Println("holidays: ", holidays)
}
CodePudding user response:
I had to adjust the Response struct
to handle correct unmarshaling of data. Find below the working code:
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type Response map[string]Data
type Data struct {
Division string `json:"division"`
Events []struct {
Title string `json:"title"`
Date string `json:"date"`
Notes string `json:"notes"`
Bunting bool `json:"bunting"`
} `json:"events"`
}
func main() {
resp, err := http.Get("https://www.gov.uk/bank-holidays.json")
if err != nil {
log.Fatal(err)
}
if resp.Body != nil {
defer resp.Body.Close()
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
var response Response
if err = json.Unmarshal(body, &response); err != nil {
log.Fatalln(err)
}
for div, _ := range response {
for _, event := range response[div].Events {
fmt.Printf("Division=%s, Holiday=%s, Date=%s\n", div, event.Title, event.Date)
}
}
}
CodePudding user response:
Because your json fields must match your structs.
type Response map[string]Data
type Data struct {
Division string `json:"division"`
Events []Event `json:"events"`
}
type Event struct {
Title string `json:"title"`
Date string `json:"date"`
Notes string `json:"notes"`
Bunting bool `json:"bunting"`
}