Как получить имена json-полей структуры в 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).Name)
}
}
Конечно, я получаю:
Id
CreatedAt
Tag
Text
AuthorId
Но мне хотелось бы что-то вроде:
id
created_at
tag
text
author_id
Ответы
Ответ 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
поддерживает больше, чем просто имена полей, такие как omitempty
или string
, поэтому, если вам нужен подход, который также позаботится об этом, необходимо внести дополнительные улучшения в функцию PrintFields
:
- нам нужно проверить, является ли тег
json
-
(т.е. json:"-"
) - нам нужно проверить, существует ли имя и изолировать его
Что-то вроде этого:
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)
}
}
Ответ 2
Вместо StructField
Name
вы можете использовать Tag
для получения объекта StructTag
.
См.: https://golang.org/pkg/reflect/#StructTag
Затем вы можете использовать методы StructTag
Get
или 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"))
}
}
Посмотрите на игровая площадка.
Ответ 4
Не 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
обновленная версия с универсальным интерфейсом в качестве параметра:
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)
}
}