feat: conf add FillDefault func

master
MarkJoyMa 2 years ago committed by Kevin Wan
parent ba71964b16
commit f3cf891d4f

@ -13,12 +13,17 @@ import (
"github.com/zeromicro/go-zero/internal/encoding" "github.com/zeromicro/go-zero/internal/encoding"
) )
var loaders = map[string]func([]byte, any) error{ const jsonTagKey = "json"
var (
fillDefaultUnmarshaler = mapping.NewUnmarshaler(jsonTagKey, mapping.WithDefault())
loaders = map[string]func([]byte, any) error{
".json": LoadFromJsonBytes, ".json": LoadFromJsonBytes,
".toml": LoadFromTomlBytes, ".toml": LoadFromTomlBytes,
".yaml": LoadFromYamlBytes, ".yaml": LoadFromYamlBytes,
".yml": LoadFromYamlBytes, ".yml": LoadFromYamlBytes,
} }
)
// children and mapField should not be both filled. // children and mapField should not be both filled.
// named fields and map cannot be bound to the same field name. // named fields and map cannot be bound to the same field name.
@ -27,6 +32,11 @@ type fieldInfo struct {
mapField *fieldInfo mapField *fieldInfo
} }
// FillDefault fills the default values for the given v.
func FillDefault(v any) error {
return fillDefaultUnmarshaler.Unmarshal(map[string]any{}, v)
}
// Load loads config into v from file, .json, .yaml and .yml are acceptable. // Load loads config into v from file, .json, .yaml and .yml are acceptable.
func Load(file string, v any, opts ...Option) error { func Load(file string, v any, opts ...Option) error {
content, err := os.ReadFile(file) content, err := os.ReadFile(file)

@ -1039,3 +1039,43 @@ func createTempFile(ext, text string) (string, error) {
return filename, nil return filename, nil
} }
func TestFillDefaultUnmarshal(t *testing.T) {
t.Run("nil", func(t *testing.T) {
type St struct{}
err := FillDefault(St{})
assert.Error(t, err)
})
t.Run("not nil", func(t *testing.T) {
type St struct{}
err := FillDefault(&St{})
assert.NoError(t, err)
})
t.Run("default", func(t *testing.T) {
type St struct {
A string `json:",default=a"`
B string
}
var st St
err := FillDefault(&st)
assert.NoError(t, err)
assert.Equal(t, st.A, "a")
})
t.Run("env", func(t *testing.T) {
type St struct {
A string `json:",default=a"`
B string
C string `json:",env=TEST_C"`
}
t.Setenv("TEST_C", "c")
var st St
err := FillDefault(&st)
assert.NoError(t, err)
assert.Equal(t, st.A, "a")
assert.Equal(t, st.C, "c")
})
}

@ -47,6 +47,7 @@ type (
UnmarshalOption func(*unmarshalOptions) UnmarshalOption func(*unmarshalOptions)
unmarshalOptions struct { unmarshalOptions struct {
fillDefault bool
fromString bool fromString bool
canonicalKey func(key string) string canonicalKey func(key string) string
} }
@ -710,7 +711,7 @@ func (u *Unmarshaler) processNamedField(field reflect.StructField, value reflect
valuer := createValuer(m, opts) valuer := createValuer(m, opts)
mapValue, hasValue := getValue(valuer, canonicalKey) mapValue, hasValue := getValue(valuer, canonicalKey)
if !hasValue { if !hasValue || u.opts.fillDefault {
return u.processNamedFieldWithoutValue(field.Type, value, opts, fullName) return u.processNamedFieldWithoutValue(field.Type, value, opts, fullName)
} }
@ -801,6 +802,10 @@ func (u *Unmarshaler) processNamedFieldWithoutValue(fieldType reflect.Type, valu
} }
} }
if u.opts.fillDefault {
return nil
}
switch fieldKind { switch fieldKind {
case reflect.Array, reflect.Map, reflect.Slice: case reflect.Array, reflect.Map, reflect.Slice:
if !opts.optional() { if !opts.optional() {
@ -873,13 +878,20 @@ func WithStringValues() UnmarshalOption {
} }
} }
// WithCanonicalKeyFunc customizes an Unmarshaler with Canonical Key func // WithCanonicalKeyFunc customizes an Unmarshaler with Canonical Key func.
func WithCanonicalKeyFunc(f func(string) string) UnmarshalOption { func WithCanonicalKeyFunc(f func(string) string) UnmarshalOption {
return func(opt *unmarshalOptions) { return func(opt *unmarshalOptions) {
opt.canonicalKey = f opt.canonicalKey = f
} }
} }
// WithDefault customizes an Unmarshaler with fill default values.
func WithDefault() UnmarshalOption {
return func(opt *unmarshalOptions) {
opt.fillDefault = true
}
}
func createValuer(v valuerWithParent, opts *fieldOptionsWithContext) valuerWithParent { func createValuer(v valuerWithParent, opts *fieldOptionsWithContext) valuerWithParent {
if opts.inherit() { if opts.inherit() {
return recursiveValuer{ return recursiveValuer{

Loading…
Cancel
Save