]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package flatmap |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | "reflect" | |
6 | ) | |
7 | ||
8 | // Flatten takes a structure and turns into a flat map[string]string. | |
9 | // | |
10 | // Within the "thing" parameter, only primitive values are allowed. Structs are | |
11 | // not supported. Therefore, it can only be slices, maps, primitives, and | |
12 | // any combination of those together. | |
13 | // | |
14 | // See the tests for examples of what inputs are turned into. | |
15 | func Flatten(thing map[string]interface{}) Map { | |
16 | result := make(map[string]string) | |
17 | ||
18 | for k, raw := range thing { | |
19 | flatten(result, k, reflect.ValueOf(raw)) | |
20 | } | |
21 | ||
22 | return Map(result) | |
23 | } | |
24 | ||
25 | func flatten(result map[string]string, prefix string, v reflect.Value) { | |
26 | if v.Kind() == reflect.Interface { | |
27 | v = v.Elem() | |
28 | } | |
29 | ||
30 | switch v.Kind() { | |
31 | case reflect.Bool: | |
32 | if v.Bool() { | |
33 | result[prefix] = "true" | |
34 | } else { | |
35 | result[prefix] = "false" | |
36 | } | |
37 | case reflect.Int: | |
38 | result[prefix] = fmt.Sprintf("%d", v.Int()) | |
39 | case reflect.Map: | |
40 | flattenMap(result, prefix, v) | |
41 | case reflect.Slice: | |
42 | flattenSlice(result, prefix, v) | |
43 | case reflect.String: | |
44 | result[prefix] = v.String() | |
45 | default: | |
46 | panic(fmt.Sprintf("Unknown: %s", v)) | |
47 | } | |
48 | } | |
49 | ||
50 | func flattenMap(result map[string]string, prefix string, v reflect.Value) { | |
51 | for _, k := range v.MapKeys() { | |
52 | if k.Kind() == reflect.Interface { | |
53 | k = k.Elem() | |
54 | } | |
55 | ||
56 | if k.Kind() != reflect.String { | |
57 | panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k)) | |
58 | } | |
59 | ||
60 | flatten(result, fmt.Sprintf("%s.%s", prefix, k.String()), v.MapIndex(k)) | |
61 | } | |
62 | } | |
63 | ||
64 | func flattenSlice(result map[string]string, prefix string, v reflect.Value) { | |
65 | prefix = prefix + "." | |
66 | ||
67 | result[prefix+"#"] = fmt.Sprintf("%d", v.Len()) | |
68 | for i := 0; i < v.Len(); i++ { | |
69 | flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i)) | |
70 | } | |
71 | } |