conf/flatten.go
juancwu c4ebd80669 Add reflective struct-tag config loader
Implements conf.Load to populate tagged structs from a chain of Sources
(env, .env, YAML/JSON/TOML, custom). Supports default values, slice
separators, nested structs, pointer fields, and a Validator hook.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:35:51 +00:00

44 lines
1 KiB
Go

package conf
import (
"fmt"
"strings"
)
// flatten walks a nested map[string]any (as produced by yaml/json/toml decoders)
// and returns a flat key->string map. Keys are uppercased and joined with "_".
// Scalar values are stringified via fmt.Sprint. Slices are joined with ",".
func flatten(in map[string]any) map[string]string {
out := map[string]string{}
flattenInto(out, "", in)
return out
}
func flattenInto(out map[string]string, prefix string, in map[string]any) {
for k, v := range in {
key := strings.ToUpper(k)
if prefix != "" {
key = prefix + "_" + key
}
switch x := v.(type) {
case map[string]any:
flattenInto(out, key, x)
case map[any]any: // yaml.v3 with non-string keys
m := make(map[string]any, len(x))
for kk, vv := range x {
m[fmt.Sprint(kk)] = vv
}
flattenInto(out, key, m)
case []any:
parts := make([]string, len(x))
for i, e := range x {
parts[i] = fmt.Sprint(e)
}
out[key] = strings.Join(parts, ",")
case nil:
// skip
default:
out[key] = fmt.Sprint(x)
}
}
}