Skip to content

Commit 673d723

Browse files
committed
feat(unmarshaler): add interface so that children nodes can define custom unmarshal behavior
1 parent 7017a68 commit 673d723

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

mapstructure.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ type Metadata struct {
301301
Unset []string
302302
}
303303

304+
type Unmarshaler interface {
305+
UnmarshalMapStructure(interface{}) error
306+
}
307+
304308
// Decode takes an input structure and uses reflection to translate it to
305309
// the output structure. output must be a pointer to a map or struct.
306310
func Decode(input interface{}, output interface{}) error {
@@ -453,6 +457,12 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
453457
return nil
454458
}
455459

460+
if outVal.CanAddr() {
461+
if v, ok := outVal.Addr().Interface().(Unmarshaler); ok {
462+
return v.UnmarshalMapStructure(input)
463+
}
464+
}
465+
456466
if d.config.DecodeHook != nil {
457467
// We have a DecodeHook, so let's pre-process the input.
458468
var err error

mapstructure_examples_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package mapstructure
22

33
import (
44
"fmt"
5+
"strconv"
56
)
67

78
func ExampleDecode() {
@@ -289,3 +290,37 @@ func ExampleDecode_omitempty() {
289290
// Output:
290291
// &map[Age:0 FirstName:Somebody]
291292
}
293+
294+
type CustomUnmarshaler struct {
295+
ID int64
296+
}
297+
298+
func (c *CustomUnmarshaler) UnmarshalMapStructure(v interface{}) error {
299+
if sid, ok := v.(string); ok {
300+
id, err := strconv.ParseInt(sid, 10, 64)
301+
if err != nil {
302+
return fmt.Errorf("error converting id to int, %v", err)
303+
}
304+
c.ID = id
305+
return nil
306+
307+
}
308+
return fmt.Errorf("error unmarshaling")
309+
}
310+
311+
func ExampleDecode_structImplementsUnmarshalerInterface() {
312+
type Custom struct {
313+
Unmarshalers []CustomUnmarshaler
314+
}
315+
input := map[string]interface{}{
316+
"unmarshalers": []string{"123456"},
317+
}
318+
var result Custom
319+
err := Decode(input, &result)
320+
if err != nil {
321+
panic(err)
322+
}
323+
fmt.Printf("%#v", result)
324+
// Output:
325+
// mapstructure.Custom{Unmarshalers:[]mapstructure.CustomUnmarshaler{mapstructure.CustomUnmarshaler{ID:123456}}}
326+
}

0 commit comments

Comments
 (0)