Go JSONをデコードする
jsonパッケージのDecoderを使うとjsonデータを簡単にパースできる。
目次
変数名で対応付ける
package main import ( "encoding/json" "fmt" "strings" ) func main() { json_data := `{"name":"Gopher","age":10}` // 入力のjsonデータ var d struct { Name string Age int } decoder := json.NewDecoder(strings.NewReader(json_data)) err := decoder.Decode(&d) fmt.Println(d.Name, d.Age, err) // Gopher 10 <nil> }
json.NewDecoder()
でjson.Decorderのポインタを取得する。json.NewDecoder()
にはio.Reader
を渡さなければいけないので、strings.NewReader(json_data)
でstrings.Reader
のポインタを渡すようにしている。
jsonデータのkeyとデータを受け取る変数名が同じだと自動で対応づけてくれるらしい。最後の出力は見ると"name":"Gopher"はNameに、"age":10はAgeに紐づいているのが分かる。
名前の対応付がうまくいかないと値が代入されない。試しに入力のjsonのageをheightに変更すると値が代入されないことがわかる。
func main() { json_data := `{"name":"Gopher","height":10}` // ageをheightに変更した var d struct { Name string Age int } decoder := json.NewDecoder(strings.NewReader(json_data)) err := decoder.Decode(&d) // d.Ageに値が代入されない fmt.Println(d.Name, d.Age, err) // Gopher 0 <nil> }
構造体タグ名で対応付ける
構造体にタグ(json:xxx
)を付与するとDecorderがそのタグを使って値を代入してくれる。
func main() { json_data := `{"Name":"Gopher","Age":10}` var d struct { ID string `json:"name"` // jsonのkeyと同じ名前を指定する Old int `json:"age"` // 大文字小文字は区別されない } decoder := json.NewDecoder(strings.NewReader(json_data)) err := decoder.Decode(&d) // jsonのkeyと変数名は一致していないが値が代入されている fmt.Println(d.ID, d.Old, err) // Gopher 10 <nil> }
json:
がないと値の代入はうまくいかない。
// これだとうまく代入されない var d struct { ID string `"name"` Old int `"age"` }
一致しないkeyがあったときにエラーを返す
これまでの例では一致しないkeyがあってもerr := decoder.Decode(&d)
でerrが帰ってくることはなかった。(常にnilだった)
decoder.DisallowUnknownFields()
をコールしておくと、一致しないkeyがあったときにerrorとして返してくれる。
func main() { json_data := `{"name":"Gopher","age":10}` var d struct { Name string `json:"name"` // ageに対応する変数がない } decoder := json.NewDecoder(strings.NewReader(json_data)) decoder.DisallowUnknownFields() // Decodeの前にコールする err := decoder.Decode(&d) // ageに対応する変数がなかったのでerrが返ってくる fmt.Println(d.Name, err) // Gopher json: unknown field "age" }