Skip to content

Commit 85ea26b

Browse files
authored
Merge pull request #1 from oneadvisory/jfb/custom-impl
Add Dispatch Impl
2 parents 878a968 + aefec66 commit 85ea26b

File tree

4 files changed

+229
-72
lines changed

4 files changed

+229
-72
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ _testmain.go
2121

2222
*.exe
2323
*.test
24+
25+
.idea

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
This is a copy of the repo https://github.com/fatih/structs which is no longer being maintained. It has been tweaked
2+
a little to better support our use case.
3+
4+
15
# Archived project. No maintenance.
26

37
This project is not maintained anymore and is archived. Feel free to fork and
@@ -40,7 +44,6 @@ server := &Server{
4044
Enabled: true,
4145
}
4246
```
43-
4447
```go
4548
// Convert a struct to a map[string]interface{}
4649
// => {"Name":"gopher", "ID":123456, "Enabled":true}
@@ -162,8 +165,8 @@ for _, f := range s.Fields() {
162165

163166
## Credits
164167

165-
* [Fatih Arslan](https://github.com/fatih)
166-
* [Cihangir Savas](https://github.com/cihangir)
168+
* [Fatih Arslan](https://github.com/fatih)
169+
* [Cihangir Savas](https://github.com/cihangir)
167170

168171
## License
169172

structs.go

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ package structs
33

44
import (
55
"fmt"
6-
76
"reflect"
7+
"strings"
8+
"time"
89
)
910

1011
var (
@@ -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.
222266
func (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.
233277
func (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

Comments
 (0)