forked from worldline-go/struct2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decoder.go
117 lines (95 loc) · 3.33 KB
/
decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package struct2
import (
"reflect"
"regexp"
)
var reIgnoreSeperator = regexp.MustCompile(`[-_ ]`)
// Decoder is main struct of struct2, holds config and functions.
type Decoder struct {
// Tagname to lookup struct's field tag, default is `struct`
TagName string
// Hooks function run before decode and enable to change of data.
Hooks []HookFunc
// Mapstructure operations
// HooksDecode to modify data before decode.
HooksDecode []HookDecodeFunc
// WeaklyTypedInput is true, the decoder will make the following
// "weak" conversions:
//
// - bools to string (true = "1", false = "0")
// - numbers to string (base 10)
// - bools to int/uint (true = 1, false = 0)
// - strings to int/uint (base implied by prefix)
// - int to bool (true if value != 0)
// - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
// FALSE, false, False. Anything else is an error)
// - empty array = empty map and vice versa
// - negative numbers to overflowed uint values (base 10)
// - slice of maps to a merged map
// - single values are converted to slices if required. Each
// element is weakly decoded. For example: "4" can become []int{4}
// if the target type is an int slice.
//
WeaklyTypedInput bool
// ZeroFields, if set to true, will zero fields before writing them.
// For example, a map will be emptied before decoded values are put in
// it. If this is false, a map will be merged.
ZeroFields bool
// Squash will squash embedded structs. A squash tag may also be
// added to an individual struct field using a tag. For example:
//
// type Parent struct {
// Child `struct:",squash"`
// }
Squash bool
// IgnoreUntaggedFields ignores all struct fields without explicit
// TagName, comparable to `struct:"-"` as default behaviour.
IgnoreUntaggedFields bool
// BackupTagName usable if TagName not found.
BackupTagName string
// WeaklyDashUnderscore apply underscore/dash conversion to variables
// on map to struct. variable_name == variable-name.
WeaklyDashUnderscore bool
// WeaklyIgnoreSeperator ignore seperator on map to struct. variable_name == variablename
// values are -, _ and space.
WeaklyIgnoreSeperator bool
// ForcePtr2 assume `struct:",ptr2` on all pointer struct fields.
ForcePtr2 bool
// OmitNullPtr omits nil pointers, in the map.
OmitNilPtr bool
// OutputCamelCase will convert map keys to camel case.
OuputCamelCase bool
// NoRemainFields will fail if there are extra fields in the input, that are not in the output.
NoRemainFields bool
}
func (d *Decoder) SetTagName(t string) *Decoder {
d.TagName = t
return d
}
func (d *Decoder) SetHooks(hooks []HookFunc) *Decoder {
d.Hooks = hooks
return d
}
func (d *Decoder) SetHooksDecode(hooksDecode []HookDecodeFunc) *Decoder {
d.HooksDecode = hooksDecode
return d
}
func (d *Decoder) tagName() string {
if d.TagName == "" {
return "struct"
}
return d.TagName
}
func (d *Decoder) getTagValue(field reflect.StructField) (string, string) {
selectedTagName := d.tagName()
tagValue := field.Tag.Get(selectedTagName)
if tagValue == "" && d.BackupTagName != "" {
selectedTagName = d.BackupTagName
tagValue = field.Tag.Get(selectedTagName)
}
return tagValue, selectedTagName
}
func (d *Decoder) parseTag(field reflect.StructField) (string, tagOptions) {
tagValue, _ := d.getTagValue(field)
return parseTag(tagValue)
}