feat: conf add FillDefault func
This commit is contained in:
@@ -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"
|
||||||
".json": LoadFromJsonBytes,
|
|
||||||
".toml": LoadFromTomlBytes,
|
var (
|
||||||
".yaml": LoadFromYamlBytes,
|
fillDefaultUnmarshaler = mapping.NewUnmarshaler(jsonTagKey, mapping.WithDefault())
|
||||||
".yml": LoadFromYamlBytes,
|
loaders = map[string]func([]byte, any) error{
|
||||||
}
|
".json": LoadFromJsonBytes,
|
||||||
|
".toml": LoadFromTomlBytes,
|
||||||
|
".yaml": 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 interface{}, opts ...Option) error {
|
func Load(file string, v interface{}, 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{
|
||||||
|
|||||||
Reference in New Issue
Block a user