Skip to content

Commit 89fdea7

Browse files
Allows custom values of hooks to be entered into a map#43
1 parent b9ad4b3 commit 89fdea7

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

decode_hooks_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,65 @@ func TestStructToMapHookFuncTabled(t *testing.T) {
10021002
}
10031003
}
10041004

1005+
func TestNestedStructFieldTypeOverride(t *testing.T) {
1006+
type Struct struct {
1007+
Time time.Time `mapstructure:"time"`
1008+
}
1009+
1010+
input := Struct{
1011+
Time: time.Now(),
1012+
}
1013+
1014+
var actualNoHook map[string]any
1015+
1016+
d, err := NewDecoder(&DecoderConfig{Result: &actualNoHook})
1017+
if err != nil {
1018+
t.Fatalf("unexpected err %#v", err)
1019+
}
1020+
1021+
expectedNoHook := map[string]any{}
1022+
1023+
err = d.Decode(input)
1024+
if err != nil {
1025+
t.Fatalf("unexpected err %#v", err)
1026+
}
1027+
1028+
if !reflect.DeepEqual(expectedNoHook, actualNoHook["time"]) {
1029+
t.Fatalf("expected %#v, got %#v", expectedNoHook, actualNoHook["time"])
1030+
}
1031+
1032+
var actualHook map[string]any
1033+
1034+
d, err = NewDecoder(&DecoderConfig{
1035+
Result: &actualHook,
1036+
DecodeHook: func(from, to reflect.Type, data any) (any, error) {
1037+
if tm, ok := data.(time.Time); ok {
1038+
return tm.Format(time.RFC3339), nil
1039+
}
1040+
1041+
if tm, ok := data.(*time.Time); ok {
1042+
return tm.Format(time.RFC3339), nil
1043+
}
1044+
1045+
return data, nil
1046+
},
1047+
})
1048+
if err != nil {
1049+
t.Fatalf("unexpected err %#v", err)
1050+
}
1051+
1052+
expectedHook := input.Time.Format(time.RFC3339)
1053+
1054+
err = d.Decode(input)
1055+
if err != nil {
1056+
t.Fatalf("unexpected err %#v", err)
1057+
}
1058+
1059+
if !reflect.DeepEqual(expectedHook, actualHook["time"]) {
1060+
t.Fatalf("expected %#v, got %#v", expectedHook, actualHook["time"])
1061+
}
1062+
}
1063+
10051064
func TestTextUnmarshallerHookFunc(t *testing.T) {
10061065
type MyString string
10071066

mapstructure.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,22 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
13701370
keyName = tagValue
13711371
}
13721372

1373+
// Allows custom values of hooks to be entered into a map
1374+
if d.cachedDecodeHook != nil {
1375+
mapelem := reflect.New(valMap.Type().Elem()).Elem()
1376+
1377+
input, err := d.cachedDecodeHook(v, mapelem)
1378+
if err != nil {
1379+
return fmt.Errorf("error decoding '%s': %w", name, err)
1380+
}
1381+
1382+
if !reflect.DeepEqual(input, v.Interface()) {
1383+
valMap.SetMapIndex(reflect.ValueOf(keyName), reflect.ValueOf(input))
1384+
1385+
continue
1386+
}
1387+
}
1388+
13731389
if v.Kind() == reflect.Struct {
13741390
x := reflect.New(v.Type())
13751391
x.Elem().Set(v)

0 commit comments

Comments
 (0)