如何获得在golang一个结构的JSON字段名?

问题描述 投票:14回答:5

是什么让这个结构的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
json go struct field
5个回答
18
投票

您可以使用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. 我们需要检查,如果名称存在,并孤立它

事情是这样的:

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

4
投票

除了使用StructFieldName的,你可以使用Tag获得StructTag对象。请参阅:https://golang.org/pkg/reflect/#StructTag

然后你可以使用StructTagGetLookup方法来获取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)
        }
    }
}

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.


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

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"))
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.