structure: add omitnested support to Fields
This commit is contained in:
parent
eacf1a7590
commit
72596462dd
59
structure.go
59
structure.go
@ -88,6 +88,37 @@ func Values(s interface{}) []interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fields returns a slice of field names. A struct tag with the content of "-"
|
||||||
|
// ignores the checking of that particular field. Example:
|
||||||
|
//
|
||||||
|
// // Field is ignored by this package.
|
||||||
|
// Field bool `structure:"-"`
|
||||||
|
//
|
||||||
|
// Note that only exported fields of a struct can be accessed, non exported
|
||||||
|
// fields will be neglected. It panics if s's kind is not struct.
|
||||||
|
func Fields(s interface{}) []string {
|
||||||
|
v, fields := strctInfo(s)
|
||||||
|
|
||||||
|
keys := make([]string, 0)
|
||||||
|
for _, field := range fields {
|
||||||
|
val := v.FieldByName(field.Name)
|
||||||
|
|
||||||
|
_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))
|
||||||
|
|
||||||
|
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
||||||
|
// look out for embedded structs, and convert them to a
|
||||||
|
// []string to be added to the final values slice
|
||||||
|
for _, embeddedVal := range Fields(val.Interface()) {
|
||||||
|
keys = append(keys, embeddedVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = append(keys, field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
// IsZero returns true if all fields in a struct is a zero value (not
|
// IsZero returns true if all fields in a struct is a zero value (not
|
||||||
// initialized) A struct tag with the content of "-" ignores the checking of
|
// initialized) A struct tag with the content of "-" ignores the checking of
|
||||||
// that particular field. Example:
|
// that particular field. Example:
|
||||||
@ -163,34 +194,6 @@ func HasZero(s interface{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields returns a slice of field names. A struct tag with the content of "-"
|
|
||||||
// ignores the checking of that particular field. Example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field bool `structure:"-"`
|
|
||||||
//
|
|
||||||
// Note that only exported fields of a struct can be accessed, non exported
|
|
||||||
// fields will be neglected. It panics if s's kind is not struct.
|
|
||||||
func Fields(s interface{}) []string {
|
|
||||||
v, fields := strctInfo(s)
|
|
||||||
|
|
||||||
keys := make([]string, 0)
|
|
||||||
for _, field := range fields {
|
|
||||||
val := v.FieldByName(field.Name)
|
|
||||||
if IsStruct(val.Interface()) {
|
|
||||||
// look out for embedded structs, and convert them to a
|
|
||||||
// []string to be added to the final values slice
|
|
||||||
for _, embeddedVal := range Fields(val.Interface()) {
|
|
||||||
keys = append(keys, embeddedVal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = append(keys, field.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStruct returns true if the given variable is a struct or a pointer to
|
// IsStruct returns true if the given variable is a struct or a pointer to
|
||||||
// struct.
|
// struct.
|
||||||
func IsStruct(s interface{}) bool {
|
func IsStruct(s interface{}) bool {
|
||||||
|
|||||||
@ -411,6 +411,43 @@ func TestFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFields_OmitNested(t *testing.T) {
|
||||||
|
type A struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
Number int
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
a := A{Name: "example"}
|
||||||
|
|
||||||
|
type B struct {
|
||||||
|
A A `structure:",omitnested"`
|
||||||
|
C int
|
||||||
|
}
|
||||||
|
b := &B{A: a, C: 123}
|
||||||
|
|
||||||
|
s := Fields(b)
|
||||||
|
|
||||||
|
if len(s) != 2 {
|
||||||
|
t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
inSlice := func(val interface{}) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if reflect.DeepEqual(v, val) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range []interface{}{"A", "C"} {
|
||||||
|
if !inSlice(val) {
|
||||||
|
t.Errorf("Fields should have the value %v", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFields_Nested(t *testing.T) {
|
func TestFields_Nested(t *testing.T) {
|
||||||
type A struct {
|
type A struct {
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user