如何在golang中获取结构的json字段名称?

时间:2016-11-29 11:30:51

标签: json go struct field

获取此结构的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

6 个答案:

答案 0 :(得分:17)

您使用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标记格式不仅支持字段名称,例如omitemptystring,因此如果您需要一种方法来处理同样,应该对PrintFields函数进行进一步的改进:

  1. 我们需要检查json代码是否为-(即json:"-"
  2. 我们需要检查名称是否存在并将其隔离
  3. 这样的事情:

    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)
        }
    }
    

答案 1 :(得分:4)

您可以使用StructField来获取Name对象,而不是使用Tag StructTag。 请参阅:https://golang.org/pkg/reflect/#StructTag

然后,您可以使用StructTag的{​​{1}}或Get方法获取json标记:

使用Lookup

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

答案 2 :(得分:2)

使用:

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.

中查看

答案 3 :(得分:2)

以通用接口作为参数的更新版本:

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)
    }
}

答案 4 :(得分:1)

不是您要找的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"))
    }
}

答案 5 :(得分:0)

func (e example) GetJsonField() []string {
    b := example{}
    marshaled, _ := json.Marshal(b)
    m := make(map[string]interface{})
    _ = json.Unmarshal(marshaled, &m)
    
    result := make([]string, 0)
    for k := range m {
        result = append(result, k)
    }
    return result
}