Merge pull request #24 from nullbus/master
Custom default tag name for each struct
This commit is contained in:
commit
c00d27128b
7
field.go
7
field.go
@ -14,8 +14,9 @@ var (
|
||||
// Field represents a single struct field that encapsulates high level
|
||||
// functions around the field.
|
||||
type Field struct {
|
||||
value reflect.Value
|
||||
field reflect.StructField
|
||||
value reflect.Value
|
||||
field reflect.StructField
|
||||
defaultTag string
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
31
structs.go
31
structs.go
@ -13,16 +13,18 @@ var (
|
||||
// Struct encapsulates a struct type to provide several high level functions
|
||||
// around the struct.
|
||||
type Struct struct {
|
||||
raw interface{}
|
||||
value reflect.Value
|
||||
raw interface{}
|
||||
value reflect.Value
|
||||
TagName string
|
||||
}
|
||||
|
||||
// New returns a new *Struct with the struct s. It panics if the s's kind is
|
||||
// not struct.
|
||||
func New(s interface{}) *Struct {
|
||||
return &Struct{
|
||||
raw: s,
|
||||
value: strctVal(s),
|
||||
raw: s,
|
||||
value: strctVal(s),
|
||||
TagName: DefaultTagName,
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +73,7 @@ func (s *Struct) Map() map[string]interface{} {
|
||||
|
||||
var finalVal interface{}
|
||||
|
||||
tagName, tagOpts := parseTag(field.Tag.Get(DefaultTagName))
|
||||
tagName, tagOpts := parseTag(field.Tag.Get(s.TagName))
|
||||
if tagName != "" {
|
||||
name = tagName
|
||||
}
|
||||
@ -131,7 +133,7 @@ func (s *Struct) Values() []interface{} {
|
||||
for _, field := range fields {
|
||||
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
|
||||
// not include
|
||||
@ -166,10 +168,10 @@ func (s *Struct) Values() []interface{} {
|
||||
//
|
||||
// It panics if s's kind is not struct.
|
||||
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 {
|
||||
v = v.Elem()
|
||||
}
|
||||
@ -181,7 +183,7 @@ func getFields(v reflect.Value) []*Field {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
|
||||
if tag := field.Tag.Get(DefaultTagName); tag == "-" {
|
||||
if tag := field.Tag.Get(tagName); tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -220,8 +222,9 @@ func (s *Struct) FieldOk(name string) (*Field, bool) {
|
||||
}
|
||||
|
||||
return &Field{
|
||||
field: field,
|
||||
value: s.value.FieldByName(name),
|
||||
field: field,
|
||||
value: s.value.FieldByName(name),
|
||||
defaultTag: s.TagName,
|
||||
}, true
|
||||
}
|
||||
|
||||
@ -247,7 +250,7 @@ func (s *Struct) IsZero() bool {
|
||||
for _, field := range fields {
|
||||
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") {
|
||||
ok := IsZero(val.Interface())
|
||||
@ -294,7 +297,7 @@ func (s *Struct) HasZero() bool {
|
||||
for _, field := range fields {
|
||||
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") {
|
||||
ok := HasZero(val.Interface())
|
||||
@ -341,7 +344,7 @@ func (s *Struct) structFields() []reflect.StructField {
|
||||
}
|
||||
|
||||
// don't check if it's omitted
|
||||
if tag := field.Tag.Get(DefaultTagName); tag == "-" {
|
||||
if tag := field.Tag.Get(s.TagName); tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@ -124,12 +124,10 @@ func TestMap_CustomTag(t *testing.T) {
|
||||
C: true,
|
||||
}
|
||||
|
||||
defaultName := DefaultTagName
|
||||
DefaultTagName = "dd"
|
||||
defer func() {
|
||||
DefaultTagName = defaultName
|
||||
}()
|
||||
a := Map(T)
|
||||
s := New(T)
|
||||
s.TagName = "dd"
|
||||
|
||||
a := s.Map()
|
||||
|
||||
inMap := func(key interface{}) bool {
|
||||
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) {
|
||||
type A struct {
|
||||
Name string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user