-
Notifications
You must be signed in to change notification settings - Fork 0
/
values.go
86 lines (73 loc) · 1.76 KB
/
values.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
package json
import (
"strconv"
"strings"
"time"
"unsafe"
"github.com/boxgo/box/pkg/config/reader"
"github.com/boxgo/box/pkg/config/source"
jsoniter "github.com/json-iterator/go"
)
type jsonValues struct {
ch *source.ChangeSet
api jsoniter.API
}
const defaultTagKey = "config"
func init() {
jsoniter.RegisterTypeDecoderFunc("time.Duration", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NumberValue:
*(*time.Duration)(ptr) = time.Duration(iter.ReadInt64()) * time.Second
case jsoniter.StringValue:
str := iter.ReadString()
duration, err := time.ParseDuration(str)
if err != nil {
iter.ReportError("time.ParseDuration", err.Error())
} else {
*(*time.Duration)(ptr) = duration
}
default:
*(*interface{})(ptr) = iter.Read()
}
})
}
func newValues(ch *source.ChangeSet) (reader.Values, error) {
api := jsoniter.Config{
EscapeHTML: true,
SortMapKeys: true,
ValidateJsonRawMessage: true,
TagKey: defaultTagKey,
}.Froze()
return &jsonValues{
ch: ch,
api: api,
}, nil
}
func (j *jsonValues) Bytes() []byte {
return j.ch.Data
}
func (j *jsonValues) Get(path ...string) reader.Value {
p := []interface{}{}
for _, pit := range path {
for _, it := range strings.Split(pit, ".") {
if i, err := strconv.ParseInt(it, 10, 32); err == nil {
p = append(p, int(i))
} else {
p = append(p, it)
}
}
}
return &jsonValue{
api: j.api,
value: j.api.Get(j.Bytes(), p...),
}
}
func (j *jsonValues) Map() map[string]interface{} {
return j.api.Get(j.ch.Data).GetInterface().(map[string]interface{})
}
func (j *jsonValues) Scan(v interface{}) error {
if len(j.ch.Data) == 0 {
return nil
}
return j.api.Unmarshal(j.ch.Data, v)
}