Go構造体の`json:hoge`の正体を探る
TL;DR
type Person struct {
Name string `json:"name"`
}
-
`json:"name"`
は構造体のタグ
-
reflect.TypeOf(Person).Field(0).Get("json")
で取り出せる!
はじめに
type Person struct {
Name string `json:"name"`
}
`json:"name"`
は構造体のタグreflect.TypeOf(Person).Field(0).Get("json")
で取り出せる!Go言語でjsonを扱うとき、構造体定義にjsonのフィールド名を書くと思います。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
}
おまじないと思って深く考えず使っていましたが、
- そもそも
`json:"name"`
って何? - ただのコメント?
- jsonのためだけの特別構文?
という疑問がわいたので調べてみました。
json:hoge は構造体のタグ
公式ドキュメントに早速答えがありました。ちゃんとふだんから読みなさい
The Go Programming Language Specification - The Go Programming Language
A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. An empty tag string is equivalent to an absent tag. The tags are made visible through a reflection interface and take part in type identity for structs but are otherwise ignored.
フィールド宣言の後にはオプションで文字列リテラルのタグを付けることが可能で、これはフィールド宣言に対応する全てのフィールドの属性となります。空文字列のタグはタグ無しの場合と同等です。タグはリフレクションインターフェースにより可視化され、構造体の型の一意性1に関与しますが、それ以外の場合は無視されます。
(日本語は拙訳)
`json:"hoge"`
は構造体のタグであり、もともとGo言語にある構文を使っている(json用の特別なものではない)ことが分かります。
タグの取り出し方
ドキュメントの通り、タグはreflect
を使って取り出すことができます。
import (
"fmt"
"reflect"
)
type Person struct {
Name string `my name`
Age int `Don't look at this!`
}
func main() {
person := Person{Name: "Taro", Age: 23}
// リフレクションで型情報取得
personType := reflect.TypeOf(person)
for i := 0; i < personType.NumField(); i++ {
// タグを取得
tag := personType.Field(i).Tag
fmt.Println(tag)
}
}
my name
Don't look at this!
タグ内のキー
これだけでも便利ですが、タグをkey:"value"
の形式で書くことで複数の属性を持たせることができます。キーに対応する値はTag.Get(key)
で取り出せます。
encoding/json
はタグ中のjson
キーを参照していたのですね。
import (
"fmt"
"reflect"
)
type Person struct {
Name string `json:"name" `
Age int `json:"age"`
// 他のキーも定義
Address string `json:"address" description:"where he lives" country:"Japan"`
}
func main() {
person := Person{Name: "Taro", Age: 23, Address: "Tokyo"}
personType := reflect.TypeOf(person)
fmt.Println(personType.Field(0).Tag.Get("json")) // name
fmt.Println(personType.Field(1).Tag.Get("json")) // age
fmt.Println(personType.Field(2).Tag.Get("json")) // address
// 他のキーも参照可能!
fmt.Println(personType.Field(2).Tag.Get("description")) // where he lives
fmt.Println(personType.Field(2).Tag.Get("country")) // Japan
}
実際にjson.Marshal
を読んでみると、(呼び出しを追うのが大変ですが)Tag.Get("json")
でフィールド名を取り出す処理が確認できます。
タグを利用するライブラリ
json以外にもxml, yaml等色々なパッケージで利用されているみたいです。上手く活用していきたいですね!
Author And Source
この問題について(Go構造体の`json:hoge`の正体を探る), 我々は、より多くの情報をここで見つけました https://qiita.com/Syuparn/items/9e6fb68afb5418893c23著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .