如何在Golang中获取结构体的JSON字段名称?

huangapple go评论89阅读模式
英文:

How to get the json field names of a struct in golang?

问题

获取该结构体的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).Tag.Get("json"))
    }
}

当然,我得到的结果是:

id
created_at
tag
text
author_id

但我想要的结果是:

id
created_at
tag
text
author_id
英文:

What is the way to get the json field names of this struct ?

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

I try to print the fields with this function :

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

Of course I get :

Id
CreatedAt
Tag
Text
AuthorId

But I would like something like :

id
created_at
tag
text
author_id

答案1

得分: 42

你可以使用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)
    }
  }
}
英文:

You use the StructTag type to get the tags. The documentation I linked has examples, look them up, but your code could be something like

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

NOTE The json tag format supports more than just field names, such as omitempty or string, so if you need an approach that takes care of that too, further improvements to the PrintFields function should be made:

  1. we need to check whether the json tag is - (i.e. json:&quot;-&quot;)
  2. we need to check if name exists and isolate it

Something like this:

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

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

答案2

得分: 5

使用StructFieldName而不是Tag,可以使用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++ {
        // 如果字段没有json标签,则打印空行
        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++ {
        // 跳过没有json标签的字段
        if tag, ok := val.Type().Field(i).Tag.Lookup("json"); ok {
            fmt.Println(tag)
        }
    }
}
英文:

Instead of using StructField's Name, you can use Tag to get a StructTag object.
See: https://golang.org/pkg/reflect/#StructTag

Then you can use StructTag's Get or Lookup methods to get the json tag:

Using Get:

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

Using Lookup:

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

答案3

得分: 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中查看。

英文:

Use:

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

See it in playground.

答案4

得分: 3

一个带有通用接口作为参数的更新版本:

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 != "-" {
            // 检查可能的逗号,例如 "...,omitempty"
            var commaIdx int
            if commaIdx = strings.Index(jsonTag, ","); commaIdx < 0 {
                commaIdx = len(jsonTag)
            }
            fieldName = jsonTag[:commaIdx]
        }
        fmt.Println(fieldName)
    }
}
英文:

an updated version with a generic interface as parameter:

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

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

答案5

得分: 2

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

}

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

答案6

得分: 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"))
    }
}

(翻译结果已经返回,不包含其他内容)

英文:

Not the Name you are looking for. What you looking is the Tag

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

答案7

得分: 0

获取结构字段名的Json字段名

val := reflect.ValueOf(structobject)
field, _ := val.Type().FieldByName("Id")
fmt.Println(field.Tag.Get("json"))

获取Json字段名的代码部分已经翻译完成。

英文:

Get Json field name Using Struct Field Name

val := reflect.ValueOf(structobject)    
field, _ := val.Type().FieldByName(&quot;Id&quot;)
fmt.Println(field.Tag.Get(&quot;json&quot;))

huangapple
  • 本文由 发表于 2016年11月29日 19:30:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/40864840.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定