Go で Json 取扱

やりたいこと

  • Json ファイルの読み込み・構造体に格納
  • Json ファイルの書き込み時のエスケープ処理対応
  • Json ファイル出力

Json ファイルの読み込み

  • 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))
}

ioutil.ReadFile(fpath) でなく ioutil.ReadFile(filepath.Clean(fpath)) としている理由は以下参照してください。

読み取れました!

でも、この results[] の中の id が使いたいんだけどなぁ…
と思っても、このままだと id の値を取得できません。

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

struct に格納する

JSON-to-Go に json を貼り付けるとサクッと struct が生成されます。

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) で json データを hoge に格納しています。

実行すると、ちゃんと取れてます。

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

Json ファイル出力

map[int]int 型のデータを 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)
}
}

hoge.json が出力されていることが確認できます。

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

余談

json.Unmarshal の error チェックをしない実装をよく見かけます。

実装上、失敗したとて、問題ない場合があるのであれば、良いですが、基本省略すべきでないです。

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

その他、実は error 型返す関数をチェックしてないということがあるので、以下 module で対処する様にしています。

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

Go プロジェクトでは、必ず、GitHub Actions でも、ローカルでも実行する様にしています。

以上
参考になれば幸いです。

Author

Kenzo Tanaka

Posted on

2020-05-07

Licensed under

コメント