Go言語で手軽にjsonの項目をパースする
Go言語の標準ライブラリでjsonを手軽にパースする方法がよくわからなかったので調べた結果のまとめ。
標準ライブラリによるjsonパース
標準ライブラリの encoding/json
を用いてjsonをパースしようとすると構造体の定義が必要になる。これが非常に面倒。
json全体を利用するのであれば構造体を定義して操作するのは問題ないが、特定の1項目だけ取得したい場合などわざわざ構造体を定義したくない。
もちろん、 json-to-go を利用すれば、jsonから自動で構造体定義を出力するので作成の手間はないし、
不要な項目は省略しても問題ないのでシンプルに保つことはできるが、できれば構造体定義なしにjsonから値を取得したい。
type Data struct {
Depth1 struct {
Depth2 struct {
Depth3 struct {
Key string
}
}
}
}
func main() {
var jsonStr =`
{
"version": "1.0",
"depth1": {
"depth2": {
"depth3": {
"key": "pure-go-value"
}
}
}
}`
var data Data
json.Unmarshal([]byte(jsonStr), &data)
fmt.Println(data.Depth1.Depth2.Depth3.Key)
}
$ go run pure-go.go
pure-go-value
サードパーティライブラリを利用する
標準ライブラリでは解決できないのでサードパーティライブラリを利用して解決する。
調べてみたらいろいろあった。
antonholmquist/jason
antonholmquist/jasonは他に自分の用途に合ったライブラリがないか調べて一番最初に見付けたやつ。
これでも標準ライブラリに比べて十分シンプルなのでよいかなと思ったが、
追加できちんと調べてみたら実はもっとよさそうなのがたくさんあった(後述)。
func main() {
var jsonStr =`
{
"version": "1.0",
"depth1": {
"depth2": {
"depth3": {
"key": "jason-value"
}
}
}
}`
v, err := jason.NewObjectFromBytes([]byte(jsonStr))
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
key, err := v.GetString("depth1", "depth2", "depth3", "key")
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
fmt.Println(key)
}
buger/jsonparser
buger/jsonparser は自分がやりたいことがまさにREADMEに記載されている。
It does not require you to know the structure of the payload (eg. create structs), and allows accessing fields by providing the path to them. I
利用方法も antonholmquist/jason
に比べてよりシンプルでよさそう。
func main() {
var jsonStr =`
{
"version": "1.0",
"depth1": {
"depth2": {
"depth3": {
"key": "jsonparser-value"
}
}
}
}`
key, err := jsonparser.GetString([]byte(jsonStr), "depth1", "depth2", "depth3", "key")
if err != nil {
fmt.Println(os.Stderr, err)
os.Exit(1)
}
fmt.Println(key)
}
tidwall/gjson
tidwall/gjsonも似たようなライブラリだが、こちらはドットでパス表現できる。
jsonキーにドットを含む場合はバックスラッシュでエスケープすればよい
こちらの方がシンプルで使いやすいだろうか。
READMEを見る限りでは gjson の方が速くて高機能。
また、スター数や利用者数も多い。
func main() {
var jsonStr =
`{
"version": "1.0",
"depth1": {
"depth2": {
"depth3": {
"key": "gjson-value"
"test.data": "dot-value"
}
}
}
}`
key := gjson.Get(jsonStr, "depth1.depth2.depth3.key").String()
dot := gjson.Get(jsonStr, "depth1.depth2.depth3.key.test\\.data").String()
fmt.Println(key)
fmt.Println(dot)
}
まとめ
gjsonがよさそう
Discussion