diff --git a/structtemplater.go b/structtemplater.go index 18b7d329a..cb8288993 100644 --- a/structtemplater.go +++ b/structtemplater.go @@ -1,6 +1,7 @@ package gomplate import ( + "encoding/json" "reflect" "strings" @@ -60,13 +61,34 @@ func (w StructTemplater) StructField(f reflect.StructField, v reflect.Value) err return err } - if val.Kind() == reflect.String { - newVal, err := w.Template(val.String()) + concreteVal := reflect.ValueOf(val.Interface()) + switch concreteVal.Kind() { + case reflect.String: + newVal, err := w.Template(concreteVal.String()) if err != nil { return err } newMap.SetMapIndex(newKey, reflect.ValueOf(newVal)) - } else { + + case reflect.Map: + marshalled, err := json.Marshal(val.Interface()) + if err != nil { + newMap.SetMapIndex(newKey, val) + } else { + templated, err := w.Template(string(marshalled)) + if err != nil { + return err + } + + var unmarshalled map[string]any + if err := json.Unmarshal([]byte(templated), &unmarshalled); err != nil { + newMap.SetMapIndex(newKey, val) + } else { + newMap.SetMapIndex(newKey, reflect.ValueOf(unmarshalled)) + } + } + + default: newMap.SetMapIndex(newKey, val) } } diff --git a/structtemplater_test.go b/structtemplater_test.go index 23d0d40d5..b47b55d05 100644 --- a/structtemplater_test.go +++ b/structtemplater_test.go @@ -10,6 +10,7 @@ type Test struct { Template string `template:"true"` NoTemplate string Inner Inner + JSONMap map[string]any `template:"true"` Labels map[string]string `template:"true"` LabelsRaw map[string]string } @@ -108,6 +109,48 @@ var tests = []test{ }, }, }, + { + name: "deeply nested map", + StructTemplater: StructTemplater{ + RequiredTag: "template", + ValueFunctions: true, + Values: map[string]interface{}{ + "msg": "world", + }, + }, + Input: &Test{ + Template: "{{msg}}", + JSONMap: map[string]any{ + "a": map[string]any{ + "b": map[string]any{ + "c": "{{msg}}", + }, + "j": []map[string]any{ + { + "l": "{{msg}}", + }, + }, + }, + "e": "hello {{msg}}", + }, + }, + Output: &Test{ + Template: "world", + JSONMap: map[string]any{ + "a": map[string]any{ + "b": map[string]any{ + "c": "world", + }, + "j": []any{ + map[string]any{ + "l": "world", + }, + }, + }, + "e": "hello world", + }, + }, + }, } func TestMain(t *testing.T) {