Skip to content

Commit

Permalink
Add decodeViaJSON, benchmark and example (as a test).
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dmitshur committed Jul 17, 2015
1 parent 2caf8ef commit 42646d5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
36 changes: 36 additions & 0 deletions mapstructure_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mapstructure

import (
"encoding/json"
"testing"
)

Expand All @@ -27,6 +28,41 @@ func Benchmark_Decode(b *testing.B) {
}
}

// 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",
Expand Down
31 changes: 31 additions & 0 deletions mapstructure_examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,37 @@ func ExampleDecode() {
// 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
Expand Down

0 comments on commit 42646d5

Please sign in to comment.