Ability to parse maps.

This commit is contained in:
Stanislav Nikitin 2020-04-02 06:45:19 +05:00
parent 2290a3ee58
commit 94234816c5
No known key found for this signature in database
GPG Key ID: 106900B32F8192EE
2 changed files with 52 additions and 0 deletions

View File

@ -19,6 +19,31 @@ func composeTree(value reflect.Value, prefix string) {
} }
} }
// Resolve Ptrs if any.
for {
if value.Kind() == reflect.Ptr {
value = value.Elem()
typeOf = value.Type()
} else {
break
}
}
if value.Kind() != reflect.Struct {
f := &field{
Name: typeOf.Name(),
EnvVar: curPrefix + strings.ToUpper(typeOf.Name()),
Pointer: value,
Kind: value.Kind(),
}
parsedTree = append(parsedTree, f)
printDebug("Field data constructed: %+v", f)
return
}
for i := 0; i < value.NumField(); i++ { for i := 0; i < value.NumField(); i++ {
fieldToProcess := value.Field(i) fieldToProcess := value.Field(i)
fieldToProcessType := typeOf.Field(i) fieldToProcessType := typeOf.Field(i)
@ -79,6 +104,16 @@ func composeTree(value reflect.Value, prefix string) {
newElementPrefix = strings.ToUpper(newElementPrefix + typeOf.Field(i).Name) newElementPrefix = strings.ToUpper(newElementPrefix + typeOf.Field(i).Name)
} }
composeTree(fieldToProcess, newElementPrefix) composeTree(fieldToProcess, newElementPrefix)
} else if fieldToProcess.Kind() == reflect.Map {
newElementPrefix := curPrefix
if !fieldToProcessType.Anonymous {
newElementPrefix = strings.ToUpper(newElementPrefix + typeOf.Field(i).Name)
}
mapIter := fieldToProcess.MapRange()
for mapIter.Next() {
composeTree(mapIter.Value().Elem(), newElementPrefix+"_"+strings.ToUpper(mapIter.Key().String()))
}
} else { } else {
f := &field{ f := &field{
Name: typeOf.Field(i).Name, Name: typeOf.Field(i).Name,

View File

@ -81,6 +81,10 @@ type testStruct1 struct {
testUnexportedNest *testDatas testUnexportedNest *testDatas
} }
type testStructWithMap struct {
MapConfig map[string]interface{}
}
func setenv(prefix string) { func setenv(prefix string) {
os.Setenv(prefix+"TESTSTRING", testString) os.Setenv(prefix+"TESTSTRING", testString)
os.Setenv(prefix+"TESTINT8", strconv.FormatInt(int64(testInt8), 10)) os.Setenv(prefix+"TESTINT8", strconv.FormatInt(int64(testInt8), 10))
@ -124,6 +128,8 @@ func TestParseValidData(t *testing.T) {
setenv("TESTNESTINTERFACEPOINTER_") setenv("TESTNESTINTERFACEPOINTER_")
setenv("TESTNESTPOINTER_") setenv("TESTNESTPOINTER_")
setenv("TESTUNEXPORTEDNEST_") setenv("TESTUNEXPORTEDNEST_")
setenv("MAPCONFIG_TESTSTRUCT_")
setenv("MAPCONFIG_TESTSTRUCT_TESTNEST_")
ts := &testStruct1{} ts := &testStruct1{}
err := Parse(ts, nil) err := Parse(ts, nil)
@ -135,6 +141,15 @@ func TestParseValidData(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, testBool, ts.TestBool) require.Equal(t, testBool, ts.TestBool)
ts1 := &testStructWithMap{MapConfig: map[string]interface{}{
"teststruct": &testStruct1{},
}}
err1 := Parse(ts1, nil)
require.Nil(t, err1)
t.Logf("Parsed struct with map data: %+v\n", ts1.MapConfig["teststruct"])
unsetenv("") unsetenv("")
unsetenv("TESTNEST_") unsetenv("TESTNEST_")
unsetenv("TESTNESTANONYMOUS_") unsetenv("TESTNESTANONYMOUS_")
@ -143,6 +158,8 @@ func TestParseValidData(t *testing.T) {
unsetenv("TESTNESTINTERFACEPOINTER_") unsetenv("TESTNESTINTERFACEPOINTER_")
unsetenv("TESTNESTPOINTER_") unsetenv("TESTNESTPOINTER_")
unsetenv("TESTUNEXPORTEDNEST_") unsetenv("TESTUNEXPORTEDNEST_")
unsetenv("MAPCONFIG_TESTSTRUCT_")
unsetenv("MAPCONFIG_TESTSTRUCT_TESTNEST_")
} }
func TestParseNotPointerToStructurePassed(t *testing.T) { func TestParseNotPointerToStructurePassed(t *testing.T) {