structs: add omitempty support to Values()

This commit is contained in:
Fatih Arslan 2014-09-15 12:39:09 +03:00
parent 431c57536b
commit 6dd7cda522
2 changed files with 39 additions and 4 deletions

View File

@ -112,10 +112,16 @@ func (s *Struct) Map() map[string]interface{} {
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
// // Field is not processed further by this package.
// Field time.Time `structs:"myName,omitnested"`
// // Fields is not processed further by this package.
// Field time.Time `structs:",omitnested"`
// Field *http.Request `structs:",omitnested"`
//
// A tag value with the option of "omitempty" ignores that particular field and
// is not added to the values if the field value is empty. Example:
//
// // Field is skipped if empty
// Field string `structs:",omitempty"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields will be neglected.
func (s *Struct) Values() []interface{} {
@ -128,6 +134,17 @@ func (s *Struct) Values() []interface{} {
_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))
// if the value is a zero value and the field is marked as omitempty do
// not include
if tagOpts.Has("omitempty") {
zero := reflect.Zero(val.Type()).Interface()
current := val.Interface()
if reflect.DeepEqual(current, zero) {
continue
}
}
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
// look out for embedded structs, and convert them to a
// []interface{} to be added to the final values slice
@ -182,7 +199,7 @@ func getFields(v reflect.Value) []*Field {
}
// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. It panics if the field is not found.
// around a single struct field entity. It panics if the field is not found.
func (s *Struct) Field(name string) *Field {
f, ok := s.FieldOk(name)
if !ok {
@ -193,7 +210,7 @@ func (s *Struct) Field(name string) *Field {
}
// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. The boolean returns true if the field
// around a single struct field entity. The boolean returns true if the field
// was found.
func (s *Struct) FieldOk(name string) (*Field, bool) {
t := s.value.Type()

View File

@ -301,6 +301,24 @@ func TestValues(t *testing.T) {
}
}
func TestValues_OmitEmpty(t *testing.T) {
type A struct {
Name string
Value int `structs:",omitempty"`
}
a := A{Name: "example"}
s := Values(a)
if len(s) != 1 {
t.Errorf("Values of omitted empty fields should be not counted")
}
if s[0].(string) != "example" {
t.Errorf("Values of omitted empty fields should left the value example")
}
}
func TestValues_OmitNested(t *testing.T) {
type A struct {
Name string