Add decodeViaJSON, benchmark and example (as a test). decodeViaJSON performs faster with less memory allocations for simple uses, despite performing the task using an indirect approach. Use it as a baseline for comparing performance of mapstructure.Decode. Credit to @sqs and @gbbr for initial idea.
diff --git a/mapstructure_benchmark_test.go b/mapstructure_benchmark_test.go index b50ac36..41d2a41 100644 --- a/mapstructure_benchmark_test.go +++ b/mapstructure_benchmark_test.go
@@ -1,6 +1,7 @@ package mapstructure import ( + "encoding/json" "testing" ) @@ -27,6 +28,41 @@ } } +// decodeViaJSON takes the map data and passes it through encoding/json to convert it into the +// given Go native structure pointed to by v. v must be a pointer to a struct. +func decodeViaJSON(data interface{}, v interface{}) error { + // Perform the task by simply marshalling the input into JSON, + // then unmarshalling it into target native Go struct. + b, err := json.Marshal(data) + if err != nil { + return err + } + return json.Unmarshal(b, v) +} + +func Benchmark_DecodeViaJSON(b *testing.B) { + type Person struct { + Name string + Age int + Emails []string + Extra map[string]string + } + + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "emails": []string{"one", "two", "three"}, + "extra": map[string]string{ + "twitter": "mitchellh", + }, + } + + var result Person + for i := 0; i < b.N; i++ { + decodeViaJSON(input, &result) + } +} + func Benchmark_DecodeBasic(b *testing.B) { input := map[string]interface{}{ "vstring": "foo",
diff --git a/mapstructure_examples_test.go b/mapstructure_examples_test.go index f17c214..f42f50e 100644 --- a/mapstructure_examples_test.go +++ b/mapstructure_examples_test.go
@@ -35,6 +35,37 @@ // mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}} } +func ExampleDecodeViaJSON() { + type Person struct { + Name string + Age int + Emails []string + Extra map[string]string + } + + // This input can come from anywhere, but typically comes from + // something like decoding JSON where we're not quite sure of the + // struct initially. + input := map[string]interface{}{ + "name": "Mitchell", + "age": 91, + "emails": []string{"one", "two", "three"}, + "extra": map[string]string{ + "twitter": "mitchellh", + }, + } + + var result Person + err := decodeViaJSON(input, &result) + if err != nil { + panic(err) + } + + fmt.Printf("%#v", result) + // Output: + // mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}} +} + func ExampleDecode_errors() { type Person struct { Name string