23 VjsonNumber json.Number
26 type BasicSquash struct {
27 Test Basic `mapstructure:",squash"`
30 type Embedded struct {
35 type EmbeddedPointer struct {
40 type EmbeddedSquash struct {
41 Basic `mapstructure:",squash"`
45 type SliceAlias []string
47 type EmbeddedSlice struct {
48 SliceAlias `mapstructure:"slice_alias"`
52 type SquashOnNonStructType struct {
53 InvalidSquashType int `mapstructure:",squash"`
58 Vother map[string]string
61 type MapOfStruct struct {
62 Value map[string]Basic
70 type NestedPointer struct {
75 type NilInterface struct {
84 type SliceOfStruct struct {
93 Extra string `mapstructure:"bar,what,what"`
94 Value string `mapstructure:"foo"`
97 type TypeConversionResult struct {
114 SliceUint8ToString string
118 StringToFloat float32
119 StringToStrSlice []string
120 StringToIntSlice []int
121 SliceToMap map[string]interface{}
122 MapToSlice []interface{}
125 func TestBasicTypes(t *testing.T) {
128 input := map[string]interface{}{
136 "vjsonInt": json.Number("1234"),
137 "vjsonFloat": json.Number("1234.5"),
138 "vjsonNumber": json.Number("1234.5"),
142 err := Decode(input, &result)
144 t.Errorf("got an err: %s", err.Error())
148 if result.Vstring != "foo" {
149 t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
152 if result.Vint != 42 {
153 t.Errorf("vint value should be 42: %#v", result.Vint)
156 if result.Vuint != 42 {
157 t.Errorf("vuint value should be 42: %#v", result.Vuint)
160 if result.Vbool != true {
161 t.Errorf("vbool value should be true: %#v", result.Vbool)
164 if result.Vfloat != 42.42 {
165 t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
168 if result.Vextra != "" {
169 t.Errorf("vextra value should be empty: %#v", result.Vextra)
172 if result.vsilent != false {
173 t.Error("vsilent should not be set, it is unexported")
176 if result.Vdata != 42 {
177 t.Error("vdata should be valid")
180 if result.VjsonInt != 1234 {
181 t.Errorf("vjsonint value should be 1234: %#v", result.VjsonInt)
184 if result.VjsonFloat != 1234.5 {
185 t.Errorf("vjsonfloat value should be 1234.5: %#v", result.VjsonFloat)
188 if !reflect.DeepEqual(result.VjsonNumber, json.Number("1234.5")) {
189 t.Errorf("vjsonnumber value should be '1234.5': %T, %#v", result.VjsonNumber, result.VjsonNumber)
193 func TestBasic_IntWithFloat(t *testing.T) {
196 input := map[string]interface{}{
201 err := Decode(input, &result)
203 t.Fatalf("got an err: %s", err)
207 func TestBasic_Merge(t *testing.T) {
210 input := map[string]interface{}{
216 err := Decode(input, &result)
218 t.Fatalf("got an err: %s", err)
225 if !reflect.DeepEqual(result, expected) {
226 t.Fatalf("bad: %#v", result)
230 func TestDecode_BasicSquash(t *testing.T) {
233 input := map[string]interface{}{
237 var result BasicSquash
238 err := Decode(input, &result)
240 t.Fatalf("got an err: %s", err.Error())
243 if result.Test.Vstring != "foo" {
244 t.Errorf("vstring value should be 'foo': %#v", result.Test.Vstring)
248 func TestDecode_Embedded(t *testing.T) {
251 input := map[string]interface{}{
253 "Basic": map[string]interface{}{
254 "vstring": "innerfoo",
260 err := Decode(input, &result)
262 t.Fatalf("got an err: %s", err.Error())
265 if result.Vstring != "innerfoo" {
266 t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
269 if result.Vunique != "bar" {
270 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
274 func TestDecode_EmbeddedPointer(t *testing.T) {
277 input := map[string]interface{}{
279 "Basic": map[string]interface{}{
280 "vstring": "innerfoo",
285 var result EmbeddedPointer
286 err := Decode(input, &result)
288 t.Fatalf("err: %s", err)
291 expected := EmbeddedPointer{
297 if !reflect.DeepEqual(result, expected) {
298 t.Fatalf("bad: %#v", result)
302 func TestDecode_EmbeddedSlice(t *testing.T) {
305 input := map[string]interface{}{
306 "slice_alias": []string{"foo", "bar"},
310 var result EmbeddedSlice
311 err := Decode(input, &result)
313 t.Fatalf("got an err: %s", err.Error())
316 if !reflect.DeepEqual(result.SliceAlias, SliceAlias([]string{"foo", "bar"})) {
317 t.Errorf("slice value: %#v", result.SliceAlias)
320 if result.Vunique != "bar" {
321 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
325 func TestDecode_EmbeddedSquash(t *testing.T) {
328 input := map[string]interface{}{
333 var result EmbeddedSquash
334 err := Decode(input, &result)
336 t.Fatalf("got an err: %s", err.Error())
339 if result.Vstring != "foo" {
340 t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
343 if result.Vunique != "bar" {
344 t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
348 func TestDecode_SquashOnNonStructType(t *testing.T) {
351 input := map[string]interface{}{
352 "InvalidSquashType": 42,
355 var result SquashOnNonStructType
356 err := Decode(input, &result)
358 t.Fatal("unexpected success decoding invalid squash field type")
359 } else if !strings.Contains(err.Error(), "unsupported type for squash") {
360 t.Fatalf("unexpected error message for invalid squash field type: %s", err)
364 func TestDecode_DecodeHook(t *testing.T) {
367 input := map[string]interface{}{
371 decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
372 if from == reflect.String && to != reflect.String {
380 config := &DecoderConfig{
381 DecodeHook: decodeHook,
385 decoder, err := NewDecoder(config)
387 t.Fatalf("err: %s", err)
390 err = decoder.Decode(input)
392 t.Fatalf("got an err: %s", err)
395 if result.Vint != 5 {
396 t.Errorf("vint should be 5: %#v", result.Vint)
400 func TestDecode_DecodeHookType(t *testing.T) {
403 input := map[string]interface{}{
407 decodeHook := func(from reflect.Type, to reflect.Type, v interface{}) (interface{}, error) {
408 if from.Kind() == reflect.String &&
409 to.Kind() != reflect.String {
417 config := &DecoderConfig{
418 DecodeHook: decodeHook,
422 decoder, err := NewDecoder(config)
424 t.Fatalf("err: %s", err)
427 err = decoder.Decode(input)
429 t.Fatalf("got an err: %s", err)
432 if result.Vint != 5 {
433 t.Errorf("vint should be 5: %#v", result.Vint)
437 func TestDecode_Nil(t *testing.T) {
440 var input interface{}
445 err := Decode(input, &result)
447 t.Fatalf("err: %s", err)
450 if result.Vstring != "foo" {
451 t.Fatalf("bad: %#v", result.Vstring)
455 func TestDecode_NilInterfaceHook(t *testing.T) {
458 input := map[string]interface{}{
462 decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
463 if t.String() == "io.Writer" {
470 var result NilInterface
471 config := &DecoderConfig{
472 DecodeHook: decodeHook,
476 decoder, err := NewDecoder(config)
478 t.Fatalf("err: %s", err)
481 err = decoder.Decode(input)
483 t.Fatalf("got an err: %s", err)
487 t.Errorf("W should be nil: %#v", result.W)
491 func TestDecode_FuncHook(t *testing.T) {
494 input := map[string]interface{}{
498 decodeHook := func(f, t reflect.Type, v interface{}) (interface{}, error) {
499 if t.Kind() != reflect.Func {
503 return func() string { return val }, nil
507 config := &DecoderConfig{
508 DecodeHook: decodeHook,
512 decoder, err := NewDecoder(config)
514 t.Fatalf("err: %s", err)
517 err = decoder.Decode(input)
519 t.Fatalf("got an err: %s", err)
522 if result.Foo() != "baz" {
523 t.Errorf("Foo call result should be 'baz': %s", result.Foo())
527 func TestDecode_NonStruct(t *testing.T) {
530 input := map[string]interface{}{
535 var result map[string]string
536 err := Decode(input, &result)
538 t.Fatalf("err: %s", err)
541 if result["foo"] != "bar" {
542 t.Fatal("foo is not bar")
546 func TestDecode_StructMatch(t *testing.T) {
549 input := map[string]interface{}{
556 err := Decode(input, &result)
558 t.Fatalf("got an err: %s", err.Error())
561 if result.Vbar.Vstring != "foo" {
562 t.Errorf("bad: %#v", result)
566 func TestDecode_TypeConversion(t *testing.T) {
567 input := map[string]interface{}{
579 "BoolToString": true,
581 "FloatToUint": 42.42,
582 "FloatToBool": 42.42,
583 "FloatToString": 42.42,
584 "SliceUint8ToString": []uint8("foo"),
586 "StringToUint": "42",
588 "StringToFloat": "42.42",
589 "StringToStrSlice": "A",
590 "StringToIntSlice": "42",
591 "SliceToMap": []interface{}{},
592 "MapToSlice": map[string]interface{}{},
595 expectedResultStrict := TypeConversionResult{
607 expectedResultWeak := TypeConversionResult{
623 FloatToString: "42.42",
624 SliceUint8ToString: "foo",
628 StringToFloat: 42.42,
629 StringToStrSlice: []string{"A"},
630 StringToIntSlice: []int{42},
631 SliceToMap: map[string]interface{}{},
632 MapToSlice: []interface{}{},
635 // Test strict type conversion
636 var resultStrict TypeConversionResult
637 err := Decode(input, &resultStrict)
639 t.Errorf("should return an error")
641 if !reflect.DeepEqual(resultStrict, expectedResultStrict) {
642 t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict)
645 // Test weak type conversion
647 var resultWeak TypeConversionResult
649 config := &DecoderConfig{
650 WeaklyTypedInput: true,
654 decoder, err = NewDecoder(config)
656 t.Fatalf("err: %s", err)
659 err = decoder.Decode(input)
661 t.Fatalf("got an err: %s", err)
664 if !reflect.DeepEqual(resultWeak, expectedResultWeak) {
665 t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak)
669 func TestDecoder_ErrorUnused(t *testing.T) {
672 input := map[string]interface{}{
678 config := &DecoderConfig{
683 decoder, err := NewDecoder(config)
685 t.Fatalf("err: %s", err)
688 err = decoder.Decode(input)
690 t.Fatal("expected error")
694 func TestMap(t *testing.T) {
697 input := map[string]interface{}{
699 "vother": map[interface{}]interface{}{
706 err := Decode(input, &result)
708 t.Fatalf("got an error: %s", err)
711 if result.Vfoo != "foo" {
712 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
715 if result.Vother == nil {
716 t.Fatal("vother should not be nil")
719 if len(result.Vother) != 2 {
720 t.Error("vother should have two items")
723 if result.Vother["foo"] != "foo" {
724 t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
727 if result.Vother["bar"] != "bar" {
728 t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
732 func TestMapMerge(t *testing.T) {
735 input := map[string]interface{}{
737 "vother": map[interface{}]interface{}{
744 result.Vother = map[string]string{"hello": "world"}
745 err := Decode(input, &result)
747 t.Fatalf("got an error: %s", err)
750 if result.Vfoo != "foo" {
751 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
754 expected := map[string]string{
759 if !reflect.DeepEqual(result.Vother, expected) {
760 t.Errorf("bad: %#v", result.Vother)
764 func TestMapOfStruct(t *testing.T) {
767 input := map[string]interface{}{
768 "value": map[string]interface{}{
769 "foo": map[string]string{"vstring": "one"},
770 "bar": map[string]string{"vstring": "two"},
774 var result MapOfStruct
775 err := Decode(input, &result)
777 t.Fatalf("got an err: %s", err)
780 if result.Value == nil {
781 t.Fatal("value should not be nil")
784 if len(result.Value) != 2 {
785 t.Error("value should have two items")
788 if result.Value["foo"].Vstring != "one" {
789 t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
792 if result.Value["bar"].Vstring != "two" {
793 t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
797 func TestNestedType(t *testing.T) {
800 input := map[string]interface{}{
802 "vbar": map[string]interface{}{
810 err := Decode(input, &result)
812 t.Fatalf("got an err: %s", err.Error())
815 if result.Vfoo != "foo" {
816 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
819 if result.Vbar.Vstring != "foo" {
820 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
823 if result.Vbar.Vint != 42 {
824 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
827 if result.Vbar.Vbool != true {
828 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
831 if result.Vbar.Vextra != "" {
832 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
836 func TestNestedTypePointer(t *testing.T) {
839 input := map[string]interface{}{
841 "vbar": &map[string]interface{}{
848 var result NestedPointer
849 err := Decode(input, &result)
851 t.Fatalf("got an err: %s", err.Error())
854 if result.Vfoo != "foo" {
855 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
858 if result.Vbar.Vstring != "foo" {
859 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
862 if result.Vbar.Vint != 42 {
863 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
866 if result.Vbar.Vbool != true {
867 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
870 if result.Vbar.Vextra != "" {
871 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
875 func TestSlice(t *testing.T) {
878 inputStringSlice := map[string]interface{}{
880 "vbar": []string{"foo", "bar", "baz"},
883 inputStringSlicePointer := map[string]interface{}{
885 "vbar": &[]string{"foo", "bar", "baz"},
888 outputStringSlice := &Slice{
890 []string{"foo", "bar", "baz"},
893 testSliceInput(t, inputStringSlice, outputStringSlice)
894 testSliceInput(t, inputStringSlicePointer, outputStringSlice)
897 func TestInvalidSlice(t *testing.T) {
900 input := map[string]interface{}{
906 err := Decode(input, &result)
908 t.Errorf("expected failure")
912 func TestSliceOfStruct(t *testing.T) {
915 input := map[string]interface{}{
916 "value": []map[string]interface{}{
922 var result SliceOfStruct
923 err := Decode(input, &result)
925 t.Fatalf("got unexpected error: %s", err)
928 if len(result.Value) != 2 {
929 t.Fatalf("expected two values, got %d", len(result.Value))
932 if result.Value[0].Vstring != "one" {
933 t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
936 if result.Value[1].Vstring != "two" {
937 t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
941 func TestSliceToMap(t *testing.T) {
944 input := []map[string]interface{}{
953 var result map[string]interface{}
954 err := WeakDecode(input, &result)
956 t.Fatalf("got an error: %s", err)
959 expected := map[string]interface{}{
963 if !reflect.DeepEqual(result, expected) {
964 t.Errorf("bad: %#v", result)
968 func TestInvalidType(t *testing.T) {
971 input := map[string]interface{}{
976 err := Decode(input, &result)
978 t.Fatal("error should exist")
981 derr, ok := err.(*Error)
983 t.Fatalf("error should be kind of Error, instead: %#v", err)
986 if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
987 t.Errorf("got unexpected error: %s", err)
990 inputNegIntUint := map[string]interface{}{
994 err = Decode(inputNegIntUint, &result)
996 t.Fatal("error should exist")
999 derr, ok = err.(*Error)
1001 t.Fatalf("error should be kind of Error, instead: %#v", err)
1004 if derr.Errors[0] != "cannot parse 'Vuint', -42 overflows uint" {
1005 t.Errorf("got unexpected error: %s", err)
1008 inputNegFloatUint := map[string]interface{}{
1012 err = Decode(inputNegFloatUint, &result)
1014 t.Fatal("error should exist")
1017 derr, ok = err.(*Error)
1019 t.Fatalf("error should be kind of Error, instead: %#v", err)
1022 if derr.Errors[0] != "cannot parse 'Vuint', -42.000000 overflows uint" {
1023 t.Errorf("got unexpected error: %s", err)
1027 func TestMetadata(t *testing.T) {
1030 input := map[string]interface{}{
1032 "vbar": map[string]interface{}{
1042 config := &DecoderConfig{
1047 decoder, err := NewDecoder(config)
1049 t.Fatalf("err: %s", err)
1052 err = decoder.Decode(input)
1054 t.Fatalf("err: %s", err.Error())
1057 expectedKeys := []string{"Vbar", "Vbar.Vstring", "Vbar.Vuint", "Vfoo"}
1058 sort.Strings(md.Keys)
1059 if !reflect.DeepEqual(md.Keys, expectedKeys) {
1060 t.Fatalf("bad keys: %#v", md.Keys)
1063 expectedUnused := []string{"Vbar.foo", "bar"}
1064 if !reflect.DeepEqual(md.Unused, expectedUnused) {
1065 t.Fatalf("bad unused: %#v", md.Unused)
1069 func TestMetadata_Embedded(t *testing.T) {
1072 input := map[string]interface{}{
1078 var result EmbeddedSquash
1079 config := &DecoderConfig{
1084 decoder, err := NewDecoder(config)
1086 t.Fatalf("err: %s", err)
1089 err = decoder.Decode(input)
1091 t.Fatalf("err: %s", err.Error())
1094 expectedKeys := []string{"Vstring", "Vunique"}
1096 sort.Strings(md.Keys)
1097 if !reflect.DeepEqual(md.Keys, expectedKeys) {
1098 t.Fatalf("bad keys: %#v", md.Keys)
1101 expectedUnused := []string{}
1102 if !reflect.DeepEqual(md.Unused, expectedUnused) {
1103 t.Fatalf("bad unused: %#v", md.Unused)
1107 func TestNonPtrValue(t *testing.T) {
1110 err := Decode(map[string]interface{}{}, Basic{})
1112 t.Fatal("error should exist")
1115 if err.Error() != "result must be a pointer" {
1116 t.Errorf("got unexpected error: %s", err)
1120 func TestTagged(t *testing.T) {
1123 input := map[string]interface{}{
1129 err := Decode(input, &result)
1131 t.Fatalf("unexpected error: %s", err)
1134 if result.Value != "bar" {
1135 t.Errorf("value should be 'bar', got: %#v", result.Value)
1138 if result.Extra != "value" {
1139 t.Errorf("extra should be 'value', got: %#v", result.Extra)
1143 func TestWeakDecode(t *testing.T) {
1146 input := map[string]interface{}{
1156 if err := WeakDecode(input, &result); err != nil {
1157 t.Fatalf("err: %s", err)
1159 if result.Foo != 4 {
1160 t.Fatalf("bad: %#v", result)
1162 if result.Bar != "value" {
1163 t.Fatalf("bad: %#v", result)
1167 func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
1169 err := Decode(input, &result)
1171 t.Fatalf("got error: %s", err)
1174 if result.Vfoo != expected.Vfoo {
1175 t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
1178 if result.Vbar == nil {
1179 t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
1182 if len(result.Vbar) != len(expected.Vbar) {
1183 t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
1186 for i, v := range result.Vbar {
1187 if v != expected.Vbar[i] {
1189 "Vbar[%d] should be '%#v', got '%#v'",
1190 i, expected.Vbar[i], v)