以前にGolang で JSON を Marshal, Unmarshal する というエントリーを書きましたが、その続きです。 ファイルとして用意してある json データを読み込んで使う方法。
環境:
$ go version
go version go1.17 linux/amd64
こんな laptop.json があるとする。
{
"name": "MacBook Air",
"price": 128000
}
なお、値段は適当です。
それではこれを読み込んで使う go のコードを書きます。 適当なディレクトリを作成(ここでは myjson とします)して、初期化。
$ mkdir myjson
$ cd myjson
$ go mod init myjson
$ touch main.go
main.go を記述。
まずは、単に laptop.json を読み込んで標準出力するところまで。
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
b, err := ioutil.ReadFile("laptop.json")
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
lines := string(b)
fmt.Print(lines)
}
実行。
$ go run main.go
{
"name": "MacBook Air",
"price": 128000
}
それでは json を読み取って内容を出力できるようにします。
まず、 laptop.json の内容を表現した Laptop タイプを定義します。
type Laptop struct {
Name string `json:"name"`
Price int `json:"price"`
}
次にこの Laptop タイプに読み込んだテキストデータをアンマーシャルするコードを追加。
var aLaptop Laptop
err1 := json.Unmarshal(b, &aLaptop)
if err1 != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
json.Unmarshal() すると aLaptop が構築される感じ。なんか気持悪いけれど Go の場合だいたいこういうお作法なので慣れるしかないな。
aLaptop が意図通りできているか確認。
fmt.Print("- " + aLaptop.Name)
price := fmt.Sprintf("%v", aLaptop.Price)
fmt.Println(" -> " + price)
最後に、json のモジュール( encoding/json )を使ったので、それを先頭の import に追加しておきます。
コード全体:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Laptop struct {
Name string `json:"name"`
Price int `json:"price"`
}
func main() {
b, err := ioutil.ReadFile("laptop.json")
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
var aLaptop Laptop
err1 := json.Unmarshal(b, &aLaptop)
if err1 != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
fmt.Print("- " + aLaptop.Name)
price := fmt.Sprintf("%v", aLaptop.Price)
fmt.Println(" -> " + price)
}
では実行してみる。
$ go run main.go
- MacBook Air -> 128000
うまくいきました。
ここまでは一つのラップトップデータを読んだだけなので、あまり実用的ではない。 複数のラップトップデータの入った json を読むにはどうするか?
まずは、次のような laptopList.json を考える。
{
"laptopList": [
{
"name": "MacBook Air",
"price": 128000
},
{
"name": "MacBook Pro",
"price": 248000
}
]
}
json データが複数のラップトップを保持しているので、それ用のタイプ LaptopList タイプを追加します。
type LaptopList struct {
LaptopList []Laptop `json:"laptopList"`
}
タイプ名が LaptopList でそのフィールド名も LaptopList になっていて気持悪いのですが、とりあえずこれでいきます。
jsonを アンマーシャルする部分のコードを修正します。
var aLaptopList LaptopList
err1 := json.Unmarshal(b, &aLaptopList)
if err1 != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
コード上では Laptop を LaptopList に rename しただけですね。
コード全体はこのようになりました。
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Laptop struct {
Name string `json:"name"`
Price int `json:"price"`
}
type LaptopList struct {
LaptopList []Laptop `json:"laptopList"`
}
func main() {
b, err := ioutil.ReadFile("laptopList.json")
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
var aLaptopList LaptopList
err1 := json.Unmarshal(b, &aLaptopList)
if err1 != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
fmt.Println(aLaptopList)
}
実行。
$ go run main.go
{[{MacBook Air 128000} {MacBook Pro 248000}]}
できました。
雑に fmt.Println(aLaptopList) するのをやめて、きちんとデータを読み取るコードにします。
for _, aLaptop := range aLaptopList.LaptopList {
name := aLaptop.Name
price := fmt.Sprintf("%v", aLaptop.Price)
fmt.Println("- " + name + " -> " + price)
}
実行します。
$ go run main.go
- MacBook Air -> 128000
- MacBook Pro -> 248000
価格は適当です(二度目)! MacBook Pro はこんなに安く買えない気がする。
では、最後に実行ファイルをビルドして締めくくりとします。
$ go build
これで myjson という実行ファイルができるので、あとはこれを実行するだけです。
$ ./myjson
- MacBook Air -> 128000
- MacBook Pro -> 248000
以上です。