mirror of
https://github.com/status-im/consul.git
synced 2025-01-21 19:20:41 +00:00
Merge pull request #8106 from hashicorp/dnephin/hook-translate-keys-make-a-copy
decode: do not modify the source data in HookTranslateKeys
This commit is contained in:
parent
17382b583c
commit
7cf96ade22
@ -44,21 +44,28 @@ func HookTranslateKeys(_, to reflect.Type, data interface{}) (interface{}, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
rules := translationsForType(to)
|
rules := translationsForType(to)
|
||||||
|
// Avoid making a copy if there are no translation rules
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
result := make(map[string]interface{}, len(source))
|
||||||
for k, v := range source {
|
for k, v := range source {
|
||||||
lowerK := strings.ToLower(k)
|
lowerK := strings.ToLower(k)
|
||||||
canonKey, ok := rules[lowerK]
|
canonKey, ok := rules[lowerK]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
result[k] = v
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delete(source, k)
|
|
||||||
|
|
||||||
// if there is a value for the canonical key then keep it
|
// if there is a value for the canonical key then keep it
|
||||||
if _, ok := source[canonKey]; ok {
|
if canonValue, ok := source[canonKey]; ok {
|
||||||
|
// Assign the value for the case where canonKey == k
|
||||||
|
result[canonKey] = canonValue
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
source[canonKey] = v
|
result[canonKey] = v
|
||||||
}
|
}
|
||||||
return source, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: could be cached if it is too slow
|
// TODO: could be cached if it is too slow
|
||||||
|
@ -178,6 +178,33 @@ func TestHookTranslateKeys_TargetStructHasPointerReceiver(t *testing.T) {
|
|||||||
require.Equal(t, expected, target, "decode metadata: %#v", md)
|
require.Equal(t, expected, target, "decode metadata: %#v", md)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHookTranslateKeys_DoesNotModifySourceData(t *testing.T) {
|
||||||
|
raw := map[string]interface{}{
|
||||||
|
"S": map[string]interface{}{
|
||||||
|
"None": "no translation",
|
||||||
|
"OldOne": "value1",
|
||||||
|
"oldtwo": "value2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := Config{}
|
||||||
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
DecodeHook: HookTranslateKeys,
|
||||||
|
Result: &cfg,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, decoder.Decode(raw))
|
||||||
|
|
||||||
|
expected := map[string]interface{}{
|
||||||
|
"S": map[string]interface{}{
|
||||||
|
"None": "no translation",
|
||||||
|
"OldOne": "value1",
|
||||||
|
"oldtwo": "value2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
require.Equal(t, raw, expected)
|
||||||
|
}
|
||||||
|
|
||||||
type translateExample struct {
|
type translateExample struct {
|
||||||
FieldDefaultCanonical string `alias:"first"`
|
FieldDefaultCanonical string `alias:"first"`
|
||||||
FieldWithMapstructureTag string `alias:"second" mapstructure:"field_with_mapstruct_tag"`
|
FieldWithMapstructureTag string `alias:"second" mapstructure:"field_with_mapstruct_tag"`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user