Skip to content

Commit cb699d2

Browse files
Merge pull request #10 from carlohamalainen/carlo/examples
Add an example showing how to use a DecodeHookFunc to parse a custom …
2 parents b71c541 + 2590662 commit cb699d2

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

mapstructure_examples_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package mapstructure
22

33
import (
44
"fmt"
5+
"reflect"
6+
"strconv"
7+
"strings"
58
)
69

710
func ExampleDecode() {
@@ -289,3 +292,68 @@ func ExampleDecode_omitempty() {
289292
// Output:
290293
// &map[Age:0 FirstName:Somebody]
291294
}
295+
296+
func ExampleDecode_decodeHookFunc() {
297+
type PersonLocation struct {
298+
Latitude float64
299+
Longtitude float64
300+
}
301+
302+
type Person struct {
303+
Name string
304+
Location PersonLocation
305+
}
306+
307+
// Example of parsing messy input: here we have latitude, longitude squashed into
308+
// a single string field. We write a custom DecodeHookFunc to parse the '#' separated
309+
// values into a PersonLocation struct.
310+
input := map[string]interface{}{
311+
"name": "Mitchell",
312+
"location": "-35.2809#149.1300",
313+
}
314+
315+
toPersonLocationHookFunc := func() DecodeHookFunc {
316+
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
317+
if t != reflect.TypeOf(PersonLocation{}) {
318+
return data, nil
319+
}
320+
321+
switch f.Kind() {
322+
case reflect.String:
323+
xs := strings.Split(data.(string), "#")
324+
325+
if len(xs) == 2 {
326+
lat, errLat := strconv.ParseFloat(xs[0], 64)
327+
lon, errLon := strconv.ParseFloat(xs[1], 64)
328+
329+
if errLat == nil && errLon == nil {
330+
return PersonLocation{Latitude: lat, Longtitude: lon}, nil
331+
}
332+
} else {
333+
return data, nil
334+
}
335+
}
336+
return data, nil
337+
}
338+
}
339+
340+
var result Person
341+
342+
decoder, errDecoder := NewDecoder(&DecoderConfig{
343+
Metadata: nil,
344+
DecodeHook: toPersonLocationHookFunc(), // Here, use ComposeDecodeHookFunc to run multiple hooks.
345+
Result: &result,
346+
})
347+
if errDecoder != nil {
348+
panic(errDecoder)
349+
}
350+
351+
err := decoder.Decode(input)
352+
if err != nil {
353+
panic(err)
354+
}
355+
356+
fmt.Printf("%#v", result)
357+
// Output:
358+
// mapstructure.Person{Name:"Mitchell", Location:mapstructure.PersonLocation{Latitude:-35.2809, Longtitude:149.13}}
359+
}

0 commit comments

Comments
 (0)