diff --git a/core/conf/config.go b/core/conf/config.go index aaa69b8d..9f1baf6c 100644 --- a/core/conf/config.go +++ b/core/conf/config.go @@ -13,7 +13,10 @@ import ( "github.com/zeromicro/go-zero/internal/encoding" ) -const jsonTagKey = "json" +const ( + jsonTagKey = "json" + jsonTagSep = ',' +) var ( fillDefaultUnmarshaler = mapping.NewUnmarshaler(jsonTagKey, mapping.WithDefault()) @@ -257,7 +260,14 @@ func buildStructFieldsInfo(tp reflect.Type) (*fieldInfo, error) { func getTagName(field reflect.StructField) string { if tag, ok := field.Tag.Lookup(jsonTagKey); ok { - return tag + if pos := strings.IndexByte(tag, jsonTagSep); pos >= 0 { + tag = tag[:pos] + } + tag = strings.TrimSpace(tag) + + if len(tag) > 0 { + return tag + } } return field.Name diff --git a/core/conf/config_test.go b/core/conf/config_test.go index 5ce32051..72392511 100644 --- a/core/conf/config_test.go +++ b/core/conf/config_test.go @@ -1076,44 +1076,86 @@ func TestFillDefaultUnmarshal(t *testing.T) { func TestConfigWithJsonTag(t *testing.T) { t.Run("map with value", func(t *testing.T) { - var input = []byte(`[BannedNotificationTemplates] -[BannedNotificationTemplates.pt-BR] -EmailTemplate = "910707,2,3,4" -[BannedNotificationTemplates.ch-MY] -EmailTemplate = "910707,2,3,4"`) + var input = []byte(`[Value] +[Value.first] +Email = "foo" +[Value.second] +Email = "bar"`) - type BannedNotificationTemplates struct { - EmailTemplate string + type Value struct { + Email string } type Config struct { - BannedNotificationTemplatesMap map[string]BannedNotificationTemplates `json:"BannedNotificationTemplates"` // 各个语言的封禁模板设置, map.key=语言 + ValueMap map[string]Value `json:"Value"` } var c Config if assert.NoError(t, LoadFromTomlBytes(input, &c)) { - assert.Len(t, c.BannedNotificationTemplatesMap, 2) + assert.Len(t, c.ValueMap, 2) } }) t.Run("map with ptr value", func(t *testing.T) { - var input = []byte(`[BannedNotificationTemplates] -[BannedNotificationTemplates.pt-BR] -EmailTemplate = "910707,2,3,4" -[BannedNotificationTemplates.ch-MY] -EmailTemplate = "910707,2,3,4"`) + var input = []byte(`[Value] +[Value.first] +Email = "foo" +[Value.second] +Email = "bar"`) - type BannedNotificationTemplates struct { - EmailTemplate string + type Value struct { + Email string } type Config struct { - BannedNotificationTemplatesMap map[string]*BannedNotificationTemplates `json:"BannedNotificationTemplates"` // 各个语言的封禁模板设置, map.key=语言 + ValueMap map[string]*Value `json:"Value"` } var c Config if assert.NoError(t, LoadFromTomlBytes(input, &c)) { - assert.Len(t, c.BannedNotificationTemplatesMap, 2) + assert.Len(t, c.ValueMap, 2) + } + }) + + t.Run("map with optional", func(t *testing.T) { + var input = []byte(`[Value] +[Value.first] +Email = "foo" +[Value.second] +Email = "bar"`) + + type Value struct { + Email string + } + + type Config struct { + Value map[string]Value `json:",optional"` + } + + var c Config + if assert.NoError(t, LoadFromTomlBytes(input, &c)) { + assert.Len(t, c.Value, 2) + } + }) + + t.Run("map with empty tag", func(t *testing.T) { + var input = []byte(`[Value] +[Value.first] +Email = "foo" +[Value.second] +Email = "bar"`) + + type Value struct { + Email string + } + + type Config struct { + Value map[string]Value `json:" "` + } + + var c Config + if assert.NoError(t, LoadFromTomlBytes(input, &c)) { + assert.Len(t, c.Value, 2) } }) } diff --git a/core/mapping/utils.go b/core/mapping/utils.go index 5ac706fe..88886228 100644 --- a/core/mapping/utils.go +++ b/core/mapping/utils.go @@ -255,7 +255,7 @@ func parseGroupedSegments(val string) []string { // don't modify returned fieldOptions, it's cached and shared among different calls. func parseKeyAndOptions(tagName string, field reflect.StructField) (string, *fieldOptions, error) { - value := field.Tag.Get(tagName) + value := strings.TrimSpace(field.Tag.Get(tagName)) if len(value) == 0 { return field.Name, nil, nil } diff --git a/core/mapping/utils_test.go b/core/mapping/utils_test.go index 854ffa46..84e0acf2 100644 --- a/core/mapping/utils_test.go +++ b/core/mapping/utils_test.go @@ -144,6 +144,10 @@ func TestParseSegments(t *testing.T) { input: "", expect: []string{}, }, + { + input: " ", + expect: []string{}, + }, { input: ",", expect: []string{""},