web-dev-qa-db-ja.com

golangで構造体のjsonフィールド名を取得するにはどうすればよいですか?

この構造体のjsonフィールド名を取得する方法は何ですか?

type example struct {
    Id          int `json:"id"`
    CreatedAt   string `json:"created_at"`
    Tag         string `json:"tag"`
    Text        string `json:"text"`
    AuthorId    int `json:"author_id"`
}

私はこの関数でフィールドを印刷しようとします:

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        fmt.Println(val.Type().Field(i).Name)
    }
}

もちろん私は得る:

Id
CreatedAt
Tag
Text
AuthorId

しかし、私は次のようなものが欲しいです:

id
created_at
tag
text
author_id
22
lambher

StructTag タイプを使用してタグを取得します。私がリンクしたドキュメントには例があり、それらを調べますが、あなたのコードは次のようなものになる可能性があります

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        fmt.Println(val.Type().Field(i).Tag.Get("json"))
    }
}

[〜#〜]注[〜#〜]jsonタグ形式は、omitemptyまたはstringなので、それにも対応できるアプローチが必要な場合は、PrintFields関数をさらに改善する必要があります。

  1. jsonタグが-であるかどうかを確認する必要があります(つまり、json:"-"
  2. 名前が存在するかどうかを確認し、それを分離する必要があります

このようなもの:

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        t := val.Type().Field(i)
        fieldName := t.Name

        if jsonTag := t.Tag.Get("json"); jsonTag != "" && jsonTag != "-" {
            if commaIdx := strings.Index(jsonTag, ","); commaIdx > 0 {
                fieldName = jsonTag[:commaIdx]
            }
        }


        fmt.Println(fieldName)
    }
}
18
ain

StructFieldNameを使用する代わりに、Tagを使用してStructTagオブジェクトを取得できます。参照: https://golang.org/pkg/reflect/#StructTag

次に、StructTagGetまたはLookupメソッドを使用して、jsonタグを取得できます。

Getの使用:

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        // prints empty line if there is no json tag for the field
        fmt.Println(val.Type().Field(i).Tag.Get("json"))
    }
}

Lookupの使用:

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        // skips fields without json tag
        if tag, ok := val.Type().Field(i).Tag.Lookup("json"); ok {
            fmt.Println(tag)
        }
    }
}
4
jussius

使用する:

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    t := val.Type()
    for i := 0; i < t.NumField(); i++ {
        fmt.Println(t.Field(i).Tag.Get("json"))
    }
}

playground。 で確認してください。

2
sadlil

パラメーターとして汎用インターフェースを備えた更新バージョン:

func PrintFields(b interface{}) {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        t := val.Type().Field(i)
        fieldName := t.Name

        if jsonTag := t.Tag.Get("json"); jsonTag != "" && jsonTag != "-" {
            // check for possible comma as in "...,omitempty"
            var commaIdx int
            if commaIdx = strings.Index(jsonTag, ","); commaIdx < 0 {
                commaIdx = len(jsonTag)
            }
            fieldName = jsonTag[:commaIdx]
        }
        fmt.Println(fieldName)
    }
}
2
ChuckM

お探しのNameではありません。あなたが探しているのはTagです

func (b example) PrintFields() {
    val := reflect.ValueOf(b)
    for i := 0; i < val.Type().NumField(); i++ {
        fmt.Println(val.Type().Field(i).Tag.Get("json"))
    }
}
1
Wendy Adi