【问题标题】:How to get the json field names of a struct in golang?如何在golang中获取结构的json字段名称?
【发布时间】:2017-04-13 09:18:12
【问题描述】:

这个结构的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


【解决方案1】:

您使用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

    switch jsonTag := t.Tag.Get("json"); jsonTag {
    case "-":
    case "":
        fmt.Println(fieldName)
    default:
        parts := strings.Split(jsonTag, ",")
        name := parts[0]
        if name == "" {
            name = fieldName
        }
        fmt.Println(name)
    }
  }
}

【讨论】:

  • 请注意,json 标记不仅支持属性名称,例如 &lt;name&gt;,omitempty,而且您的代码会因为返回的不仅仅是字段名称而失败。
【解决方案2】:

您可以使用Tag 来获取StructTag 对象,而不是使用StructFieldName。 见: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)
        }
    }
}

【讨论】:

    【解决方案3】:

    用途:

    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.

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:
          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
          }
          

          【讨论】:

            猜你喜欢
            • 2020-01-13
            • 1970-01-01
            • 2016-09-05
            • 1970-01-01
            • 2015-11-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-11
            相关资源
            最近更新 更多