@@ -3,8 +3,9 @@ package structs
33
44import (
55 "fmt"
6-
76 "reflect"
7+ "strings"
8+ "time"
89)
910
1011var (
@@ -38,43 +39,43 @@ func New(s interface{}) *Struct {
3839// can be changed in the struct field's tag value. The "structs" key in the
3940// struct's field tag value is the key name. Example:
4041//
41- // // Field appears in map as key "myName".
42- // Name string `structs:"myName"`
42+ // // Field appears in map as key "myName".
43+ // Name string `structs:"myName"`
4344//
4445// A tag value with the content of "-" ignores that particular field. Example:
4546//
46- // // Field is ignored by this package.
47- // Field bool `structs:"-"`
47+ // // Field is ignored by this package.
48+ // Field bool `structs:"-"`
4849//
4950// A tag value with the content of "string" uses the stringer to get the value. Example:
5051//
51- // // The value will be output of Animal's String() func.
52- // // Map will panic if Animal does not implement String().
53- // Field *Animal `structs:"field,string"`
52+ // // The value will be output of Animal's String() func.
53+ // // Map will panic if Animal does not implement String().
54+ // Field *Animal `structs:"field,string"`
5455//
5556// A tag value with the option of "flatten" used in a struct field is to flatten its fields
5657// in the output map. Example:
5758//
58- // // The FieldStruct's fields will be flattened into the output map.
59- // FieldStruct time.Time `structs:",flatten"`
59+ // // The FieldStruct's fields will be flattened into the output map.
60+ // FieldStruct time.Time `structs:",flatten"`
6061//
6162// A tag value with the option of "omitnested" stops iterating further if the type
6263// is a struct. Example:
6364//
64- // // Field is not processed further by this package.
65- // Field time.Time `structs:"myName,omitnested"`
66- // Field *http.Request `structs:",omitnested"`
65+ // // Field is not processed further by this package.
66+ // Field time.Time `structs:"myName,omitnested"`
67+ // Field *http.Request `structs:",omitnested"`
6768//
6869// A tag value with the option of "omitempty" ignores that particular field if
6970// the field value is empty. Example:
7071//
71- // // Field appears in map as key "myName", but the field is
72- // // skipped if empty.
73- // Field string `structs:"myName,omitempty"`
72+ // // Field appears in map as key "myName", but the field is
73+ // // skipped if empty.
74+ // Field string `structs:"myName,omitempty"`
7475//
75- // // Field appears in map as key "Field" (the default), but
76- // // the field is skipped if empty.
77- // Field string `structs:",omitempty"`
76+ // // Field appears in map as key "Field" (the default), but
77+ // // the field is skipped if empty.
78+ // Field string `structs:",omitempty"`
7879//
7980// Note that only exported fields of a struct can be accessed, non exported
8081// fields will be neglected.
@@ -139,35 +140,78 @@ func (s *Struct) FillMap(out map[string]interface{}) {
139140 continue
140141 }
141142
143+ format := getFormatTag (tagOpts )
144+
142145 if isSubStruct && (tagOpts .Has ("flatten" )) {
143146 for k := range finalVal .(map [string ]interface {}) {
144147 out [k ] = finalVal .(map [string ]interface {})[k ]
145148 }
146149 } else {
150+ if reflect .ValueOf (finalVal ).Kind () == reflect .Ptr {
151+ switch reflect .ValueOf (finalVal ).Elem ().Kind () {
152+ case reflect .String , reflect .Float64 , reflect .Float32 , reflect .Bool , reflect .Int , reflect .Int64 , reflect .Int8 , reflect .Int16 :
153+ out [name ] = reflect .ValueOf (finalVal ).Elem ().Interface ()
154+ case reflect .Struct :
155+ if reflect .TypeOf (finalVal ).AssignableTo (reflect .TypeOf (new (time.Time ))) {
156+ if format == "" {
157+ format = time .RFC3339
158+ }
159+ out [name ] = (* finalVal .(* time.Time )).Format (format )
160+ continue
161+ }
162+
163+ fallthrough
164+ default :
165+ out [name ] = finalVal
166+ }
167+ continue
168+ }
169+ if isSubStruct && reflect .TypeOf (finalVal ).AssignableTo (reflect .TypeOf (time.Time {})) {
170+ if format == "" {
171+ format = time .RFC3339
172+ }
173+ out [name ] = (finalVal .(time.Time )).Format (format )
174+ continue
175+ }
176+
147177 out [name ] = finalVal
148178 }
149179 }
150180}
151181
182+ func getFormatTag (options tagOptions ) string {
183+ for _ , opt := range options {
184+ formatKeyValue := strings .Split (opt , "=" )
185+ if len (formatKeyValue ) < 2 {
186+ return ""
187+ }
188+ if strings .ToLower (formatKeyValue [0 ]) == "format" {
189+ return formatKeyValue [1 ]
190+ }
191+ }
192+
193+ return ""
194+ }
195+
152196// Values converts the given s struct's field values to a []interface{}. A
153197// struct tag with the content of "-" ignores the that particular field.
154198// Example:
155199//
156- // // Field is ignored by this package.
157- // Field int `structs:"-"`
200+ // // Field is ignored by this package.
201+ // Field int `structs:"-"`
158202//
159203// A value with the option of "omitnested" stops iterating further if the type
160204// is a struct. Example:
161205//
162- // // Fields is not processed further by this package.
163- // Field time.Time `structs:",omitnested"`
164- // Field *http.Request `structs:",omitnested"`
206+ // // Fields is not processed further by this package.
207+ // Field time.Time `structs:",omitnested"`
208+ // Field *http.Request `structs:",omitnested"`
165209//
166210// A tag value with the option of "omitempty" ignores that particular field and
167211// is not added to the values if the field value is empty. Example:
168212//
169- // // Field is skipped if empty
170- // Field string `structs:",omitempty"`
213+ // // Field is skipped if empty
214+ // Field string `structs:",omitempty"`
171215//
172216// Note that only exported fields of a struct can be accessed, non exported
173217// fields will be neglected.
@@ -215,8 +259,8 @@ func (s *Struct) Values() []interface{} {
215259// Fields returns a slice of Fields. A struct tag with the content of "-"
216260// ignores the checking of that particular field. Example:
217261//
218- // // Field is ignored by this package.
219- // Field bool `structs:"-"`
262+ // // Field is ignored by this package.
263+ // Field bool `structs:"-"`
220264//
221265// It panics if s's kind is not struct.
222266func (s * Struct ) Fields () []* Field {
@@ -226,8 +270,8 @@ func (s *Struct) Fields() []*Field {
226270// Names returns a slice of field names. A struct tag with the content of "-"
227271// ignores the checking of that particular field. Example:
228272//
229- // // Field is ignored by this package.
230- // Field bool `structs:"-"`
273+ // // Field is ignored by this package.
274+ // Field bool `structs:"-"`
231275//
232276// It panics if s's kind is not struct.
233277func (s * Struct ) Names () []string {
@@ -303,15 +347,15 @@ func (s *Struct) FieldOk(name string) (*Field, bool) {
303347// initialized) A struct tag with the content of "-" ignores the checking of
304348// that particular field. Example:
305349//
306- // // Field is ignored by this package.
307- // Field bool `structs:"-"`
350+ // // Field is ignored by this package.
351+ // Field bool `structs:"-"`
308352//
309353// A value with the option of "omitnested" stops iterating further if the type
310354// is a struct. Example:
311355//
312- // // Field is not processed further by this package.
313- // Field time.Time `structs:"myName,omitnested"`
314- // Field *http.Request `structs:",omitnested"`
356+ // // Field is not processed further by this package.
357+ // Field time.Time `structs:"myName,omitnested"`
358+ // Field *http.Request `structs:",omitnested"`
315359//
316360// Note that only exported fields of a struct can be accessed, non exported
317361// fields will be neglected. It panics if s's kind is not struct.
@@ -350,15 +394,15 @@ func (s *Struct) IsZero() bool {
350394// A struct tag with the content of "-" ignores the checking of that particular
351395// field. Example:
352396//
353- // // Field is ignored by this package.
354- // Field bool `structs:"-"`
397+ // // Field is ignored by this package.
398+ // Field bool `structs:"-"`
355399//
356400// A value with the option of "omitnested" stops iterating further if the type
357401// is a struct. Example:
358402//
359- // // Field is not processed further by this package.
360- // Field time.Time `structs:"myName,omitnested"`
361- // Field *http.Request `structs:",omitnested"`
403+ // // Field is not processed further by this package.
404+ // Field time.Time `structs:"myName,omitnested"`
405+ // Field *http.Request `structs:",omitnested"`
362406//
363407// Note that only exported fields of a struct can be accessed, non exported
364408// fields will be neglected. It panics if s's kind is not struct.
0 commit comments