Kevin Wan 2 anos atrás
pai
commit
9c6b516bb8

+ 18 - 0
core/conf/config_test.go

@@ -123,6 +123,24 @@ d = "abcd"
 	}
 }
 
+func TestConfigWithLower(t *testing.T) {
+	text := `a = "foo"
+b = 1
+`
+	tmpfile, err := createTempFile(".toml", text)
+	assert.Nil(t, err)
+	defer os.Remove(tmpfile)
+
+	var val struct {
+		A string `json:"a"`
+		b int
+	}
+	if assert.NoError(t, Load(tmpfile, &val)) {
+		assert.Equal(t, "foo", val.A)
+		assert.Equal(t, 0, val.b)
+	}
+}
+
 func TestConfigJsonCanonical(t *testing.T) {
 	text := []byte(`{"a": "foo", "B": "bar"}`)
 

+ 7 - 6
core/mapping/unmarshaler.go

@@ -695,6 +695,10 @@ func (u *Unmarshaler) processFieldWithEnvValue(fieldType reflect.Type, value ref
 
 func (u *Unmarshaler) processNamedField(field reflect.StructField, value reflect.Value,
 	m valuerWithParent, fullName string) error {
+	if !field.IsExported() {
+		return nil
+	}
+
 	key, opts, err := u.parseOptionsWithContext(field, m, fullName)
 	if err != nil {
 		return err
@@ -869,12 +873,9 @@ func (u *Unmarshaler) unmarshalWithFullName(m valuerWithParent, v any, fullName
 
 	numFields := baseType.NumField()
 	for i := 0; i < numFields; i++ {
-		field := baseType.Field(i)
-		if !field.IsExported() {
-			continue
-		}
-
-		if err := u.processField(field, valElem.Field(i), m, fullName); err != nil {
+		typeField := baseType.Field(i)
+		valueField := valElem.Field(i)
+		if err := u.processField(typeField, valueField, m, fullName); err != nil {
 			return err
 		}
 	}

+ 46 - 0
core/mapping/unmarshaler_test.go

@@ -53,6 +53,52 @@ func TestUnmarshalWithoutTagName(t *testing.T) {
 	}
 }
 
+func TestUnmarshalWithLowerField(t *testing.T) {
+	type (
+		Lower struct {
+			value int `key:"lower"`
+		}
+
+		inner struct {
+			Lower
+			Optional bool `key:",optional"`
+		}
+	)
+	m := map[string]any{
+		"Optional": true,
+		"lower":    1,
+	}
+
+	var in inner
+	if assert.NoError(t, UnmarshalKey(m, &in)) {
+		assert.True(t, in.Optional)
+		assert.Equal(t, 0, in.value)
+	}
+}
+
+func TestUnmarshalWithLowerAnonymousStruct(t *testing.T) {
+	type (
+		lower struct {
+			Value int `key:"lower"`
+		}
+
+		inner struct {
+			lower
+			Optional bool `key:",optional"`
+		}
+	)
+	m := map[string]any{
+		"Optional": true,
+		"lower":    1,
+	}
+
+	var in inner
+	if assert.NoError(t, UnmarshalKey(m, &in)) {
+		assert.True(t, in.Optional)
+		assert.Equal(t, 1, in.Value)
+	}
+}
+
 func TestUnmarshalWithoutTagNameWithCanonicalKey(t *testing.T) {
 	type inner struct {
 		Name string `key:"name"`