forked from matryer/m
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathset.go
67 lines (60 loc) · 1.7 KB
/
set.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
package m
import (
"reflect"
"strconv"
"strings"
)
// Set sets the value in the map at the given keypath.
// For more information on supported keypaths, see Get.
// If an expected object is missing, a map[string]interface{}
// will be created and assigned to the appropriate key.
func Set(m map[string]interface{}, keypath string, value interface{}) {
setOK(m, strings.Split(keypath, dot), value)
}
// SetOK sets the value from the map by the given dot-notation
// keypath, or returns false if any of the data is missing.
// For more information on supported keypaths, see Get.
func SetOK(m map[string]interface{}, keypath string, value interface{}) bool {
return setOK(m, strings.Split(keypath, dot), value)
}
func setOK(m map[string]interface{}, keys []string, value interface{}) bool {
if m == nil {
return false
}
k := keys[0]
if len(keys) > 1 {
var sub interface{}
var ok bool
if sub, ok = get(m, k); !ok {
// sub object is nil - create it
sub = make(map[string]interface{})
m[k] = sub
}
var submap map[string]interface{}
if submap, ok = sub.(map[string]interface{}); !ok {
// not a map, so we can't set it
return false
}
return setOK(submap, keys[1:], value)
}
return set(m, k, value)
}
// set sets the value to the key.
// Supports array setting: arr[2]=val.
func set(m map[string]interface{}, k string, value interface{}) bool {
if k[len(k)-1] == closingBracket {
segs := strings.Split(k, openingBracket)
i, err := strconv.ParseInt(segs[1][0:len(segs[1])-1], 10, 64)
if err != nil {
return false
}
sub, ok := get(m, segs[0])
if !ok {
return false
}
reflect.ValueOf(sub).Index(int(i)).Set(reflect.ValueOf(value))
return true
}
m[k] = value
return true
}