Add WeaklyTypedMode for automatic string/number/bool and slice/map conversion
diff --git a/mapstructure.go b/mapstructure.go
index a84a489..d95886f 100644
--- a/mapstructure.go
+++ b/mapstructure.go
@@ -12,6 +12,7 @@
 	"fmt"
 	"reflect"
 	"sort"
+	"strconv"
 	"strings"
 )
 
@@ -23,6 +24,15 @@
 	// (extra keys).
 	ErrorUnused bool
 
+	// If WeaklyTypedInput is true, the decoder will convert values between
+	// the following types:
+	//
+	//    - numbers and bools
+	//    - strings and numbers
+	//    - strings and bools
+	//    - empty arrays/slices and empty maps
+	WeaklyTypedInput bool
+
 	// Metadata is the struct that will contain extra metadata about
 	// the decoding. If this is nil, then no metadata will be tracked.
 	Metadata *Metadata
@@ -129,11 +139,11 @@
 
 	switch dataKind {
 	case reflect.Bool:
-		fallthrough
+		err = d.decodeBool(name, data, val)
 	case reflect.Interface:
-		fallthrough
-	case reflect.String:
 		err = d.decodeBasic(name, data, val)
+	case reflect.String:
+		err = d.decodeString(name, data, val)
 	case reflect.Int:
 		err = d.decodeInt(name, data, val)
 	case reflect.Uint:
@@ -190,17 +200,58 @@
 	return nil
 }
 
+func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error {
+	dataVal := reflect.ValueOf(data)
+	dataKind := d.getKind(dataVal)
+
+	switch {
+	case dataKind == reflect.String:
+		val.SetString(dataVal.String())
+	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+		if dataVal.Bool() {
+			val.SetString("1")
+		} else {
+			val.SetString("0")
+		}
+	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
+		val.SetString(strconv.FormatInt(dataVal.Int(), 10))
+	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
+		val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
+	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
+		val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
+	default:
+		return fmt.Errorf(
+			"'%s' expected type '%s', got unconvertible type '%s'",
+			name, val.Type(), dataVal.Type())
+	}
+
+	return nil
+}
+
 func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error {
 	dataVal := reflect.ValueOf(data)
 	dataKind := d.getKind(dataVal)
 
-	switch dataKind {
-	case reflect.Int:
+	switch {
+	case dataKind == reflect.Int:
 		val.SetInt(dataVal.Int())
-	case reflect.Uint:
+	case dataKind == reflect.Uint:
 		val.SetInt(int64(dataVal.Uint()))
-	case reflect.Float32:
+	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+		if dataVal.Bool() {
+			val.SetInt(1)
+		} else {
+			val.SetInt(0)
+		}
+	case dataKind == reflect.Float32:
 		val.SetInt(int64(dataVal.Float()))
+	case dataKind == reflect.String && d.config.WeaklyTypedInput:
+		i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits())
+		if err == nil {
+			val.SetInt(i)
+		} else {
+			return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
+		}
 	default:
 		return fmt.Errorf(
 			"'%s' expected type '%s', got unconvertible type '%s'",
@@ -214,13 +265,57 @@
 	dataVal := reflect.ValueOf(data)
 	dataKind := d.getKind(dataVal)
 
-	switch dataKind {
-	case reflect.Int:
+	switch {
+	case dataKind == reflect.Int:
 		val.SetUint(uint64(dataVal.Int()))
-	case reflect.Uint:
+	case dataKind == reflect.Uint:
 		val.SetUint(dataVal.Uint())
-	case reflect.Float32:
+	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+		if dataVal.Bool() {
+			val.SetUint(1)
+		} else {
+			val.SetUint(0)
+		}
+	case dataKind == reflect.Float32:
 		val.SetUint(uint64(dataVal.Float()))
+	case dataKind == reflect.String && d.config.WeaklyTypedInput:
+		i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits())
+		if err == nil {
+			val.SetUint(i)
+		} else {
+			return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
+		}
+	default:
+		return fmt.Errorf(
+			"'%s' expected type '%s', got unconvertible type '%s'",
+			name, val.Type(), dataVal.Type())
+	}
+
+	return nil
+}
+
+func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error {
+	dataVal := reflect.ValueOf(data)
+	dataKind := d.getKind(dataVal)
+
+	switch {
+	case dataKind == reflect.Bool:
+		val.SetBool(dataVal.Bool())
+	case dataKind == reflect.Int && d.config.WeaklyTypedInput:
+		val.SetBool(dataVal.Int() != 0)
+	case dataKind == reflect.Uint && d.config.WeaklyTypedInput:
+		val.SetBool(dataVal.Uint() != 0)
+	case dataKind == reflect.Float32 && d.config.WeaklyTypedInput:
+		val.SetBool(dataVal.Float() != 0)
+	case dataKind == reflect.String && d.config.WeaklyTypedInput:
+		b, err := strconv.ParseBool(dataVal.String())
+		if err == nil {
+			val.SetBool(b)
+		} else if dataVal.String() == "" {
+			val.SetBool(false)
+		} else {
+			return fmt.Errorf("cannot parse '%s' as bool: %s", name, err)
+		}
 	default:
 		return fmt.Errorf(
 			"'%s' expected type '%s', got unconvertible type '%s'",
@@ -234,13 +329,26 @@
 	dataVal := reflect.ValueOf(data)
 	dataKind := d.getKind(dataVal)
 
-	switch dataKind {
-	case reflect.Int:
+	switch {
+	case dataKind == reflect.Int:
 		val.SetFloat(float64(dataVal.Int()))
-	case reflect.Uint:
+	case dataKind == reflect.Uint:
 		val.SetFloat(float64(dataVal.Uint()))
-	case reflect.Float32:
+	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
+		if dataVal.Bool() {
+			val.SetFloat(1)
+		} else {
+			val.SetFloat(0)
+		}
+	case dataKind == reflect.Float32:
 		val.SetFloat(float64(dataVal.Float()))
+	case dataKind == reflect.String && d.config.WeaklyTypedInput:
+		f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits())
+		if err == nil {
+			val.SetFloat(f)
+		} else {
+			return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
+		}
 	default:
 		return fmt.Errorf(
 			"'%s' expected type '%s', got unconvertible type '%s'",
@@ -251,11 +359,6 @@
 }
 
 func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
-	dataVal := reflect.Indirect(reflect.ValueOf(data))
-	if dataVal.Kind() != reflect.Map {
-		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
-	}
-
 	valType := val.Type()
 	valKeyType := valType.Key()
 	valElemType := valType.Elem()
@@ -264,6 +367,20 @@
 	mapType := reflect.MapOf(valKeyType, valElemType)
 	valMap := reflect.MakeMap(mapType)
 
+	// Check input type
+	dataVal := reflect.Indirect(reflect.ValueOf(data))
+	if dataVal.Kind() != reflect.Map {
+		// Accept empty array/slice instead of an empty map in weakly typed mode
+		if d.config.WeaklyTypedInput &&
+			(dataVal.Kind() == reflect.Slice || dataVal.Kind() == reflect.Array) &&
+			dataVal.Len() == 0 {
+			val.Set(valMap)
+			return nil
+		} else {
+			return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind())
+		}
+	}
+
 	// Accumulate errors
 	errors := make([]string, 0)
 
@@ -302,11 +419,6 @@
 func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
 	dataVal := reflect.Indirect(reflect.ValueOf(data))
 	dataValKind := dataVal.Kind()
-	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
-		return fmt.Errorf(
-			"'%s': source data must be an array or slice, got %s", name, dataValKind)
-	}
-
 	valType := val.Type()
 	valElemType := valType.Elem()
 
@@ -314,6 +426,18 @@
 	sliceType := reflect.SliceOf(valElemType)
 	valSlice := reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len())
 
+	// Check input type
+	if dataValKind != reflect.Array && dataValKind != reflect.Slice {
+		// Accept empty map instead of array/slice in weakly typed mode
+		if d.config.WeaklyTypedInput && dataVal.Kind() == reflect.Map && dataVal.Len() == 0 {
+			val.Set(valSlice)
+			return nil
+		} else {
+			return fmt.Errorf(
+				"'%s': source data must be an array or slice, got %s", name, dataValKind)
+		}
+	}
+
 	// Accumulate any errors
 	errors := make([]string, 0)
 
diff --git a/mapstructure_examples_test.go b/mapstructure_examples_test.go
index d7f3d00..27de1db 100644
--- a/mapstructure_examples_test.go
+++ b/mapstructure_examples_test.go
@@ -62,11 +62,11 @@
 	// Output:
 	// 5 error(s) decoding:
 	//
-	// * 'Name' expected type 'string', got 'int'
+	// * 'Name' expected type 'string', got unconvertible type 'int'
 	// * 'Age' expected type 'int', got unconvertible type 'string'
-	// * 'Emails[0]' expected type 'string', got 'int'
-	// * 'Emails[1]' expected type 'string', got 'int'
-	// * 'Emails[2]' expected type 'string', got 'int'
+	// * 'Emails[0]' expected type 'string', got unconvertible type 'int'
+	// * 'Emails[1]' expected type 'string', got unconvertible type 'int'
+	// * 'Emails[2]' expected type 'string', got unconvertible type 'int'
 }
 
 func ExampleDecode_metadata() {
@@ -107,3 +107,39 @@
 	// Output:
 	// Unused keys: []string{"email"}
 }
+
+func ExampleDecode_WeaklyTypedInput() {
+	type Person struct {
+		Name   string
+		Age    int
+		Emails []string
+	}
+
+	// This input can come from anywhere, but typically comes from
+	// something like decoding JSON, generated by a weakly typed language
+	// such as PHP.
+	input := map[string]interface{}{
+		"name":   123,                      // number => string
+		"age":    "42",                     // string => number
+		"emails": map[string]interface{}{}, // empty map => empty array
+	}
+
+	var result Person
+	config := &DecoderConfig{
+		WeaklyTypedInput: true,
+		Result:           &result,
+	}
+
+	decoder, err := NewDecoder(config)
+	if err != nil {
+		panic(err)
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		panic(err)
+	}
+
+	fmt.Printf("%#v", result)
+	// Output: mapstructure.Person{Name:"123", Age:42, Emails:[]string{}}
+}
diff --git a/mapstructure_test.go b/mapstructure_test.go
index f459ca8..47c98f7 100644
--- a/mapstructure_test.go
+++ b/mapstructure_test.go
@@ -54,6 +54,31 @@
 	Value string `mapstructure:"foo"`
 }
 
+type TypeConversionResult struct {
+	IntToFloat    float32
+	IntToUint     uint
+	IntToBool     bool
+	IntToString   string
+	UintToInt     int
+	UintToFloat   float32
+	UintToBool    bool
+	UintToString  string
+	BoolToInt     int
+	BoolToUint    uint
+	BoolToFloat   float32
+	BoolToString  string
+	FloatToInt    int
+	FloatToUint   uint
+	FloatToBool   bool
+	FloatToString string
+	StringToInt   int
+	StringToUint  uint
+	StringToBool  bool
+	StringToFloat float32
+	SliceToMap    map[string]interface{}
+	MapToSlice    []interface{}
+}
+
 func TestBasicTypes(t *testing.T) {
 	t.Parallel()
 
@@ -121,6 +146,103 @@
 	}
 }
 
+func TestTypeConversion(t *testing.T) {
+	input := map[string]interface{}{
+		"IntToFloat":    42,
+		"IntToUint":     42,
+		"IntToBool":     1,
+		"IntToString":   42,
+		"UintToInt":     42,
+		"UintToFloat":   42,
+		"UintToBool":    42,
+		"UintToString":  42,
+		"BoolToInt":     true,
+		"BoolToUint":    true,
+		"BoolToFloat":   true,
+		"BoolToString":  true,
+		"FloatToInt":    42.42,
+		"FloatToUint":   42.42,
+		"FloatToBool":   42.42,
+		"FloatToString": 42.42,
+		"StringToInt":   "42",
+		"StringToUint":  "42",
+		"StringToBool":  "1",
+		"StringToFloat": "42.42",
+		"SliceToMap":    []interface{} {},
+		"MapToSlice":    map[string]interface{} {},
+	}
+
+	expectedResultStrict := TypeConversionResult{
+		IntToFloat:    42.0,
+		IntToUint:     42,
+		UintToInt:     42,
+		UintToFloat:   42,
+		BoolToInt:     0,
+		BoolToUint:    0,
+		BoolToFloat:   0,
+		FloatToInt:    42,
+		FloatToUint:   42,
+	}
+
+	expectedResultWeak := TypeConversionResult{
+		IntToFloat:    42.0,
+		IntToUint:     42,
+		IntToBool:     true,
+		IntToString:   "42",
+		UintToInt:     42,
+		UintToFloat:   42,
+		UintToBool:    true,
+		UintToString:  "42",
+		BoolToInt:     1,
+		BoolToUint:    1,
+		BoolToFloat:   1,
+		BoolToString:  "1",
+		FloatToInt:    42,
+		FloatToUint:   42,
+		FloatToBool:   true,
+		FloatToString: "42.42",
+		StringToInt:   42,
+		StringToUint:  42,
+		StringToBool:  true,
+		StringToFloat: 42.42,
+		SliceToMap:    map[string]interface{} {},
+		MapToSlice:    []interface{} {},
+	}
+
+	// Test strict type conversion
+	var resultStrict TypeConversionResult
+	err := Decode(input, &resultStrict)
+	if err == nil {
+		t.Errorf("should return an error")
+	}
+	if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
+		t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
+	}
+
+	// Test weak type conversion
+	var decoder *Decoder
+	var resultWeak TypeConversionResult
+
+	config := &DecoderConfig{
+		WeaklyTypedInput: true,
+		Result:           &resultWeak,
+	}
+
+	decoder, err = NewDecoder(config)
+	if err != nil {
+		t.Fatalf("err: %s", err)
+	}
+
+	err = decoder.Decode(input)
+	if err != nil {
+		t.Fatalf("got an err: %s", err)
+	}
+
+	if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
+		t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
+	}
+}
+
 func TestDecode_Embedded(t *testing.T) {
 	t.Parallel()
 
@@ -432,7 +554,7 @@
 		t.Fatalf("error should be kind of Error, instead: %#v", err)
 	}
 
-	if derr.Errors[0] != "'Vstring' expected type 'string', got 'int'" {
+	if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
 		t.Errorf("got unexpected error: %s", err)
 	}
 }