-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson.go
84 lines (73 loc) · 1.96 KB
/
json.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
package lflag
import (
"encoding/json"
"io"
"os"
"strings"
)
type sourceJSON struct {
innerSrc Source
testJSONFile io.Reader // used as a fake json file in tests
}
// NewSourceJSON wraps an existing Source and adds support for reading a json
// file to source parameter values. The values coming from the inner Source will
// overwrite any which are found in the json file
func NewSourceJSON(inner Source) Source {
return sourceJSON{innerSrc: inner}
}
func (sj sourceJSON) Parse(pp []Param) (map[string]string, error) {
const paramName = "config-json-file"
pp = append(pp, Param{
ParamType: ParamTypeString,
Name: paramName,
Usage: "Name of json file to parse config object out of. Environment and CLI params overwrite json ones",
})
m, err := sj.innerSrc.Parse(pp)
if err != nil {
return nil, err
}
// if the parsed m contains a config file set, or a test one is given, make
// a json decoder out of that. otherwise return the m we have
var dec *json.Decoder
if jsonConfigFile := m[paramName]; jsonConfigFile != "" {
f, err := os.Open(jsonConfigFile)
if err != nil {
return nil, err
}
defer f.Close()
dec = json.NewDecoder(f)
} else if sj.testJSONFile != nil {
dec = json.NewDecoder(sj.testJSONFile)
} else {
return m, nil
}
// parse into a json map
var jm map[string]json.RawMessage
if err := dec.Decode(&jm); err != nil {
return nil, err
}
// now transform the map[string]json.RawMessage into a map[string]string
// using the json stringers
out := make(map[string]string, len(jm))
for _, p := range pp {
// we treat null and unset as the same thing
j, ok := jm[strings.ToLower(p.Name)]
if !ok {
continue
}
if string(j) == "null" {
continue
}
str, err := paramTypeJSONStringers[p.ParamType](j)
if err != nil {
return nil, err
}
out[p.Name] = str
}
// merge m into out (so the inner source values overwrite this ones') and
// return that
for k, v := range m {
out[k] = v
}
return out, nil
}