Merge pull request #24 from nullbus/master

Custom default tag name for each struct
This commit is contained in:
Fatih Arslan 2015-03-04 18:10:49 +02:00
commit c00d27128b
3 changed files with 50 additions and 23 deletions

View File

@ -14,8 +14,9 @@ var (
// Field represents a single struct field that encapsulates high level // Field represents a single struct field that encapsulates high level
// functions around the field. // functions around the field.
type Field struct { type Field struct {
value reflect.Value value reflect.Value
field reflect.StructField field reflect.StructField
defaultTag string
} }
// Tag returns the value associated with key in the tag string. If there is no // Tag returns the value associated with key in the tag string. If there is no
@ -92,7 +93,7 @@ func (f *Field) Set(val interface{}) error {
// //
// It panics if field is not exported or if field's kind is not struct // It panics if field is not exported or if field's kind is not struct
func (f *Field) Fields() []*Field { func (f *Field) Fields() []*Field {
return getFields(f.value) return getFields(f.value, f.defaultTag)
} }
// Field returns the field from a nested struct. It panics if the nested struct // Field returns the field from a nested struct. It panics if the nested struct

View File

@ -13,16 +13,18 @@ var (
// Struct encapsulates a struct type to provide several high level functions // Struct encapsulates a struct type to provide several high level functions
// around the struct. // around the struct.
type Struct struct { type Struct struct {
raw interface{} raw interface{}
value reflect.Value value reflect.Value
TagName string
} }
// New returns a new *Struct with the struct s. It panics if the s's kind is // New returns a new *Struct with the struct s. It panics if the s's kind is
// not struct. // not struct.
func New(s interface{}) *Struct { func New(s interface{}) *Struct {
return &Struct{ return &Struct{
raw: s, raw: s,
value: strctVal(s), value: strctVal(s),
TagName: DefaultTagName,
} }
} }
@ -71,7 +73,7 @@ func (s *Struct) Map() map[string]interface{} {
var finalVal interface{} var finalVal interface{}
tagName, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) tagName, tagOpts := parseTag(field.Tag.Get(s.TagName))
if tagName != "" { if tagName != "" {
name = tagName name = tagName
} }
@ -131,7 +133,7 @@ func (s *Struct) Values() []interface{} {
for _, field := range fields { for _, field := range fields {
val := s.value.FieldByName(field.Name) val := s.value.FieldByName(field.Name)
_, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) _, tagOpts := parseTag(field.Tag.Get(s.TagName))
// if the value is a zero value and the field is marked as omitempty do // if the value is a zero value and the field is marked as omitempty do
// not include // not include
@ -166,10 +168,10 @@ func (s *Struct) Values() []interface{} {
// //
// It panics if s's kind is not struct. // It panics if s's kind is not struct.
func (s *Struct) Fields() []*Field { func (s *Struct) Fields() []*Field {
return getFields(s.value) return getFields(s.value, s.TagName)
} }
func getFields(v reflect.Value) []*Field { func getFields(v reflect.Value, tagName string) []*Field {
if v.Kind() == reflect.Ptr { if v.Kind() == reflect.Ptr {
v = v.Elem() v = v.Elem()
} }
@ -181,7 +183,7 @@ func getFields(v reflect.Value) []*Field {
for i := 0; i < t.NumField(); i++ { for i := 0; i < t.NumField(); i++ {
field := t.Field(i) field := t.Field(i)
if tag := field.Tag.Get(DefaultTagName); tag == "-" { if tag := field.Tag.Get(tagName); tag == "-" {
continue continue
} }
@ -220,8 +222,9 @@ func (s *Struct) FieldOk(name string) (*Field, bool) {
} }
return &Field{ return &Field{
field: field, field: field,
value: s.value.FieldByName(name), value: s.value.FieldByName(name),
defaultTag: s.TagName,
}, true }, true
} }
@ -247,7 +250,7 @@ func (s *Struct) IsZero() bool {
for _, field := range fields { for _, field := range fields {
val := s.value.FieldByName(field.Name) val := s.value.FieldByName(field.Name)
_, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) _, tagOpts := parseTag(field.Tag.Get(s.TagName))
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
ok := IsZero(val.Interface()) ok := IsZero(val.Interface())
@ -294,7 +297,7 @@ func (s *Struct) HasZero() bool {
for _, field := range fields { for _, field := range fields {
val := s.value.FieldByName(field.Name) val := s.value.FieldByName(field.Name)
_, tagOpts := parseTag(field.Tag.Get(DefaultTagName)) _, tagOpts := parseTag(field.Tag.Get(s.TagName))
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
ok := HasZero(val.Interface()) ok := HasZero(val.Interface())
@ -341,7 +344,7 @@ func (s *Struct) structFields() []reflect.StructField {
} }
// don't check if it's omitted // don't check if it's omitted
if tag := field.Tag.Get(DefaultTagName); tag == "-" { if tag := field.Tag.Get(s.TagName); tag == "-" {
continue continue
} }

View File

@ -124,12 +124,10 @@ func TestMap_CustomTag(t *testing.T) {
C: true, C: true,
} }
defaultName := DefaultTagName s := New(T)
DefaultTagName = "dd" s.TagName = "dd"
defer func() {
DefaultTagName = defaultName a := s.Map()
}()
a := Map(T)
inMap := func(key interface{}) bool { inMap := func(key interface{}) bool {
for k := range a { for k := range a {
@ -148,6 +146,31 @@ func TestMap_CustomTag(t *testing.T) {
} }
func TestMap_MultipleCustomTag(t *testing.T) {
var A = struct {
X string `aa:"ax"`
}{"a_value"}
aStruct := New(A)
aStruct.TagName = "aa"
var B = struct {
X string `bb:"bx"`
}{"b_value"}
bStruct := New(B)
bStruct.TagName = "bb"
a, b := aStruct.Map(), bStruct.Map()
if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) {
t.Error("Map should have field ax with value a_value")
}
if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) {
t.Error("Map should have field bx with value b_value")
}
}
func TestMap_OmitEmpty(t *testing.T) { func TestMap_OmitEmpty(t *testing.T) {
type A struct { type A struct {
Name string Name string