Skip to content

Commit

Permalink
Add StructAllFieldNames function
Browse files Browse the repository at this point in the history
  • Loading branch information
demdxx committed Dec 5, 2023
1 parent 6213783 commit c72f683
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
48 changes: 48 additions & 0 deletions struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,36 @@ func ReflectStructFieldNames(t reflect.Type, tag string) []string {
return fields
}

// StructAllFieldNames returns the field names from the structure including names from tags
func StructAllFieldNames(st any, tags ...string) map[string][]string {
return StructAllFieldNamesContext(context.Background(), st, tags...)
}

// StructAllFieldNamesContext returns the field names from the structure including names from tags
func StructAllFieldNamesContext(ctx context.Context, st any, tags ...string) map[string][]string {
return ReflectStructAllFieldNamesContext(ctx, reflectTarget(reflect.ValueOf(st)).Type(), tags...)
}

// ReflectStructAllFieldNames returns the field names from the structure including names from tags
func ReflectStructAllFieldNames(t reflect.Type, tags ...string) map[string][]string {
return ReflectStructAllFieldNamesContext(context.Background(), t, tags...)
}

// ReflectStructAllFieldNamesContext returns the field names from the structure including names from tags
func ReflectStructAllFieldNamesContext(ctx context.Context, t reflect.Type, tags ...string) map[string][]string {
if t.Kind() != reflect.Struct {
return nil
}
fields := make(map[string][]string, t.NumField())
for i := 0; i < t.NumField(); i++ {
tfield := t.Field(i)
if fnames := filedNameAndTags(tfield, tags...); len(fnames) > 0 {
fields[tfield.Name] = fnames
}
}
return fields
}

// StructFieldTags returns Map with key->tag matching
func StructFieldTags(st any, tag string) map[string]string {
fields := map[string]string{}
Expand Down Expand Up @@ -417,3 +447,21 @@ func fieldTag(f reflect.StructField, tag string) string {
}
return f.Name
}

func filedNameAndTags(f reflect.StructField, tags ...string) []string {
names := []string{f.Name}
if len(tags) == 0 {
return names
}
deDup := map[string]bool{f.Name: true}
for _, tag := range tags {
if tag == "-" || tag == "" {
continue
}
if tagName := strings.TrimSuffix(f.Tag.Get(tag), ",omitempty"); tagName != "" && tagName != "-" && !deDup[tagName] {
deDup[tagName] = true
names = append(names, tagName)
}
}
return names
}
14 changes: 14 additions & 0 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gocast

import (
"context"
"reflect"
"testing"
"time"

Expand Down Expand Up @@ -198,6 +199,19 @@ func TestStructFieldTags(t *testing.T) {
"ignore": "ignore"}, fields)
}

func TestStructAllFieldNames(t *testing.T) {
fields := StructAllFieldNames(struct {
F string `field:"f" json:"F"`
J int `field:"j" json:"J"`
}{}, "field", "json")
assert.True(t, reflect.DeepEqual(fields, map[string][]string{
"F": {"F", "f"},
"J": {"J", "j"},
}))

assert.Nil(t, StructAllFieldNames(map[string]string{}, "field", "json"))
}

func TestIsStruct(t *testing.T) {
assert.True(t, IsStruct(testStruct{}))
assert.False(t, IsStruct(1))
Expand Down

0 comments on commit c72f683

Please sign in to comment.