-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconsulkvjson.go
102 lines (91 loc) · 2.27 KB
/
consulkvjson.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
package consulkvjson
import (
"encoding/json"
"strconv"
"strings"
consul "github.com/hashicorp/consul/api"
)
// KV represents a KV pair
type KV struct {
Key string
Value string
}
func traverse(path string, j interface{}) ([]*KV, error) {
kvs := make([]*KV, 0)
pathPre := ""
if path != "" {
pathPre = path + "/"
}
switch j.(type) {
case []interface{}:
for sk, sv := range j.([]interface{}) {
skvs, err := traverse(pathPre+strconv.Itoa(sk), sv)
if err != nil {
return nil, err
}
kvs = append(kvs, skvs...)
}
case map[string]interface{}:
for sk, sv := range j.(map[string]interface{}) {
skvs, err := traverse(pathPre+sk, sv)
if err != nil {
return nil, err
}
kvs = append(kvs, skvs...)
}
case float64:
kvs = append(kvs, &KV{Key: path, Value: strconv.FormatFloat(j.(float64), 'f', -1, 64)})
case bool:
kvs = append(kvs, &KV{Key: path, Value: strconv.FormatBool(j.(bool))})
case nil:
kvs = append(kvs, &KV{Key: path, Value: ""})
default:
kvs = append(kvs, &KV{Key: path, Value: j.(string)})
}
return kvs, nil
}
// ToKVs takes a json byte array and returns a list of KV pairs where each key is a path in the Consul KV store
func ToKVs(jsonData []byte) ([]*KV, error) {
var i interface{}
err := json.Unmarshal(jsonData, &i)
if err != nil {
return nil, err
}
m := i.(map[string]interface{})
return traverse("", m)
}
// ToJSON converts a list of KVs to a JSON tree
func ToJSON(kvs []*KV) (map[string]interface{}, error) {
m := make(map[string]interface{})
for _, kv := range kvs {
path := strings.Split(kv.Key, "/")
var parent = m
for s, segment := range path {
if s == len(path)-1 {
parent[segment] = string(kv.Value)
} else {
if parent[segment] == nil {
parent[segment] = make(map[string]interface{})
}
switch parent[segment].(type) {
case map[string]interface{}:
parent = parent[segment].(map[string]interface{})
default:
delete(parent, segment)
}
}
}
}
return m, nil
}
// ConsulKVsToJSON converts from the consul KVPair output to json
func ConsulKVsToJSON(consulKvs consul.KVPairs) (map[string]interface{}, error) {
kvs := make([]*KV, 0)
for _, kv := range consulKvs {
kvs = append(kvs, &KV{
Key: kv.Key,
Value: string(kv.Value),
})
}
return ToJSON(kvs)
}