fix: key like TLSConfig not working (#2730)

* fix: key like TLSConfig not working

* fix: remove unnecessary code

* chore: rename variable
master
Kevin Wan 2 years ago committed by GitHub
parent ce1c02f4f9
commit c7a0ec428c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,8 +13,6 @@ import (
"github.com/zeromicro/go-zero/internal/encoding" "github.com/zeromicro/go-zero/internal/encoding"
) )
const distanceBetweenUpperAndLower = 32
var loaders = map[string]func([]byte, interface{}) error{ var loaders = map[string]func([]byte, interface{}) error{
".json": LoadFromJsonBytes, ".json": LoadFromJsonBytes,
".toml": LoadFromTomlBytes, ".toml": LoadFromTomlBytes,
@ -66,9 +64,9 @@ func LoadFromJsonBytes(content []byte, v interface{}) error {
} }
finfo := buildFieldsInfo(reflect.TypeOf(v)) finfo := buildFieldsInfo(reflect.TypeOf(v))
camelCaseKeyMap := toCamelCaseKeyMap(m, finfo) lowerCaseKeyMap := toLowerCaseKeyMap(m, finfo)
return mapping.UnmarshalJsonMap(camelCaseKeyMap, v, mapping.WithCanonicalKeyFunc(toCamelCase)) return mapping.UnmarshalJsonMap(lowerCaseKeyMap, v, mapping.WithCanonicalKeyFunc(toLowerCase))
} }
// LoadConfigFromJsonBytes loads config into v from content json bytes. // LoadConfigFromJsonBytes loads config into v from content json bytes.
@ -129,7 +127,7 @@ func buildStructFieldsInfo(tp reflect.Type) map[string]fieldInfo {
for i := 0; i < tp.NumField(); i++ { for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i) field := tp.Field(i)
name := field.Name name := field.Name
ccName := toCamelCase(name) lowerCaseName := toLowerCase(name)
ft := mapping.Deref(field.Type) ft := mapping.Deref(field.Type)
// flatten anonymous fields // flatten anonymous fields
@ -140,7 +138,7 @@ func buildStructFieldsInfo(tp reflect.Type) map[string]fieldInfo {
info[k] = v info[k] = v
} }
} else { } else {
info[ccName] = fieldInfo{ info[lowerCaseName] = fieldInfo{
name: name, name: name,
kind: ft.Kind(), kind: ft.Kind(),
} }
@ -158,7 +156,7 @@ func buildStructFieldsInfo(tp reflect.Type) map[string]fieldInfo {
fields = buildFieldsInfo(ft.Elem()) fields = buildFieldsInfo(ft.Elem())
} }
info[ccName] = fieldInfo{ info[lowerCaseName] = fieldInfo{
name: name, name: name,
kind: ft.Kind(), kind: ft.Kind(),
children: fields, children: fields,
@ -168,58 +166,18 @@ func buildStructFieldsInfo(tp reflect.Type) map[string]fieldInfo {
return info return info
} }
func toCamelCase(s string) string { func toLowerCase(s string) string {
var buf strings.Builder return strings.ToLower(s)
buf.Grow(len(s))
var capNext bool
boundary := true
for _, v := range s {
isCap := v >= 'A' && v <= 'Z'
isLow := v >= 'a' && v <= 'z'
if boundary && (isCap || isLow) {
if capNext {
if isLow {
v -= distanceBetweenUpperAndLower
}
} else {
if isCap {
v += distanceBetweenUpperAndLower
}
}
boundary = false
}
if isCap || isLow {
buf.WriteRune(v)
capNext = false
continue
}
switch v {
// '.' is used for chained keys, e.g. "grand.parent.child"
case ' ', '.', '\t':
buf.WriteRune(v)
capNext = false
boundary = true
case '_':
capNext = true
boundary = true
default:
buf.WriteRune(v)
capNext = true
}
}
return buf.String()
} }
func toCamelCaseInterface(v interface{}, info map[string]fieldInfo) interface{} { func toLowerCaseInterface(v interface{}, info map[string]fieldInfo) interface{} {
switch vv := v.(type) { switch vv := v.(type) {
case map[string]interface{}: case map[string]interface{}:
return toCamelCaseKeyMap(vv, info) return toLowerCaseKeyMap(vv, info)
case []interface{}: case []interface{}:
var arr []interface{} var arr []interface{}
for _, vvv := range vv { for _, vvv := range vv {
arr = append(arr, toCamelCaseInterface(vvv, info)) arr = append(arr, toLowerCaseInterface(vvv, info))
} }
return arr return arr
default: default:
@ -227,19 +185,19 @@ func toCamelCaseInterface(v interface{}, info map[string]fieldInfo) interface{}
} }
} }
func toCamelCaseKeyMap(m map[string]interface{}, info map[string]fieldInfo) map[string]interface{} { func toLowerCaseKeyMap(m map[string]interface{}, info map[string]fieldInfo) map[string]interface{} {
res := make(map[string]interface{}) res := make(map[string]interface{})
for k, v := range m { for k, v := range m {
ti, ok := info[k] ti, ok := info[k]
if ok { if ok {
res[k] = toCamelCaseInterface(v, ti.children) res[k] = toLowerCaseInterface(v, ti.children)
continue continue
} }
cck := toCamelCase(k) lk := toLowerCase(k)
if ti, ok = info[cck]; ok { if ti, ok = info[lk]; ok {
res[toCamelCase(k)] = toCamelCaseInterface(v, ti.children) res[lk] = toLowerCaseInterface(v, ti.children)
} else { } else {
res[k] = v res[k] = v
} }

@ -237,23 +237,23 @@ func TestToCamelCase(t *testing.T) {
}, },
{ {
input: "hello_world", input: "hello_world",
expect: "helloWorld", expect: "hello_world",
}, },
{ {
input: "Hello_world", input: "Hello_world",
expect: "helloWorld", expect: "hello_world",
}, },
{ {
input: "hello_World", input: "hello_World",
expect: "helloWorld", expect: "hello_world",
}, },
{ {
input: "helloWorld", input: "helloWorld",
expect: "helloWorld", expect: "helloworld",
}, },
{ {
input: "HelloWorld", input: "HelloWorld",
expect: "helloWorld", expect: "helloworld",
}, },
{ {
input: "hello World", input: "hello World",
@ -269,34 +269,34 @@ func TestToCamelCase(t *testing.T) {
}, },
{ {
input: "Hello World foo_bar", input: "Hello World foo_bar",
expect: "hello world fooBar", expect: "hello world foo_bar",
}, },
{ {
input: "Hello World foo_Bar", input: "Hello World foo_Bar",
expect: "hello world fooBar", expect: "hello world foo_bar",
}, },
{ {
input: "Hello World Foo_bar", input: "Hello World Foo_bar",
expect: "hello world fooBar", expect: "hello world foo_bar",
}, },
{ {
input: "Hello World Foo_Bar", input: "Hello World Foo_Bar",
expect: "hello world fooBar", expect: "hello world foo_bar",
}, },
{ {
input: "Hello.World Foo_Bar", input: "Hello.World Foo_Bar",
expect: "hello.world fooBar", expect: "hello.world foo_bar",
}, },
{ {
input: "你好 World Foo_Bar", input: "你好 World Foo_Bar",
expect: "你好 world fooBar", expect: "你好 world foo_bar",
}, },
} }
for _, test := range tests { for _, test := range tests {
test := test test := test
t.Run(test.input, func(t *testing.T) { t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.expect, toCamelCase(test.input)) assert.Equal(t, test.expect, toLowerCase(test.input))
}) })
} }
} }
@ -332,6 +332,22 @@ func TestLoadFromYamlBytes(t *testing.T) {
assert.Equal(t, "foo", val.Layer1.Layer2.Layer3) assert.Equal(t, "foo", val.Layer1.Layer2.Layer3)
} }
func TestLoadFromYamlBytesTerm(t *testing.T) {
input := []byte(`layer1:
layer2:
tls_conf: foo`)
var val struct {
Layer1 struct {
Layer2 struct {
Layer3 string `json:"tls_conf"`
}
}
}
assert.NoError(t, LoadFromYamlBytes(input, &val))
assert.Equal(t, "foo", val.Layer1.Layer2.Layer3)
}
func TestLoadFromYamlBytesLayers(t *testing.T) { func TestLoadFromYamlBytesLayers(t *testing.T) {
input := []byte(`layer1: input := []byte(`layer1:
layer2: layer2:

Loading…
Cancel
Save