Quel est le moyen d'obtenir les noms de champs JSON de cette structure?
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"`
}
J'essaie d'imprimer les champs avec cette fonction:
func (b example) PrintFields() {
val := reflect.ValueOf(b)
for i := 0; i < val.Type().NumField(); i++ {
fmt.Println(val.Type().Field(i).Name)
}
}
Bien sûr je reçois:
Id
CreatedAt
Tag
Text
AuthorId
Mais je voudrais quelque chose comme:
id
created_at
tag
text
author_id
Vous utilisez le type StructTag pour obtenir les balises. La documentation que j'ai liée contient des exemples, recherchez-les, mais votre code pourrait ressembler à quelque chose comme:
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"))
}
}
NOTE Le format de balise json
ne prend pas uniquement en charge les noms de champs, tels que omitempty
ou string
. Par conséquent, si vous avez besoin d'une approche prenant en compte cela également, vous devez apporter des améliorations supplémentaires à la fonction PrintFields
:
json
est -
(i.e. json:"-"
)Quelque chose comme ça:
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)
}
}
Au lieu d'utiliser StructField
's Name
, vous pouvez utiliser Tag
pour obtenir un objet StructTag
. Voir: https://golang.org/pkg/reflect/#StructTag _
Ensuite, vous pouvez utiliser les méthodes StructTag
's Get
ou Lookup
pour obtenir la balise json:
Utiliser 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"))
}
}
Utiliser 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)
}
}
}
Utilisation:
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"))
}
}
Voir dans terrain de jeux.
Pas la Name
que vous recherchez. Qu'est-ce que vous cherchez est la 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"))
}
}
une version mise à jour avec une interface générique en paramètre:
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)
}
}