Catalogue
Handling JSON in Go

Handling JSON in Go

🌐 日本語で読む

What we want to do

  • Read a JSON file and store it in a struct
  • Handle escaping when writing a JSON file
  • Output a JSON file

Reading a JSON file

  • hoge.json
1
2
3
4
5
6
7
8
9
{
"results": [
{
"id": 123456,
"title": "Hello, Gopher",
"active": true
}
]
}
  • main.go
1
2
3
4
5
6
7
8
func main () {
fpath := filepath.Join("hoge.json")
b, err := ioutil.ReadFile(filepath.Clean(fpath))
if err != nil {
log.Fatal(err)
}
log.Println(string(b))
}

For why I use ioutil.ReadFile(filepath.Clean(fpath)) instead of ioutil.ReadFile(fpath), please refer to the following.

It read the file successfully!

But I want to use the id inside results[]… Even if you think so, you can’t get the value of id as it is.

1
2
3
4
5
6
7
8
9
{
"results": [
{
"id": 123456,
"title": "Hello, Gopher",
"active": true
}
]
}

Storing it in a struct

If you paste the JSON into JSON-to-Go, it generates a struct in no time.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Hoge : -
type Hoge struct {
Results []struct {
ID int `json:"id"`
Title string `json:"title"`
Active bool `json:"active"`
} `json:"results"`
}

func main() {
fpath := filepath.Join("test", "hoge.json")
b, err := ioutil.ReadFile(filepath.Clean(fpath))
if err != nil {
log.Fatal(err)
}

var hoge Hoge
if err := json.Unmarshal(b, &hoge); err != nil {
log.Fatal(err)
}
log.Printf("Title: %#v", hoge.Results[0].Title)
}

json.Unmarshal(b, &hoge) stores the JSON data into hoge.

When you run it, you can see it gets the value properly.

1
2020/05/10 23:48:01 Title: "Hello, Gopher"

Outputting a JSON file

Let’s write data of type map[int]int out to hoge.json.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
a := make(map[int]int)
a[1] = 2
a[10] = 100

b, err := json.MarshalIndent(a, "", " ")
if err != nil {
log.Fatal(errors.Wrap(err, "failed json.MarshalIndent"))
}
jsonFpath := filepath.Join(filepath.Clean("hoge.json"))
if err := ioutil.WriteFile(jsonFpath, b, 0644); err != nil {
log.Fatal(err)
}
}

You can confirm that hoge.json is output.

1
2
3
4
{
"1": 2,
"10": 100
}

Side note

I often see implementations that don’t check the error of json.Unmarshal.

It may be fine if, in your implementation, there’s no problem even when it fails, but in general you shouldn’t omit it.

1
2
var hoge Hoge
json.Unmarshal(b, &hoge)

Besides that, there are cases where you’re actually not checking a function that returns an error type, so I deal with it using the following module.

1
2
go get -u github.com/kisielk/errcheck
errcheck ./...

In my Go projects, I always make sure to run it both in GitHub Actions and locally.

That’s all.
I hope this is helpful.

kenzo0107

kenzo0107