Full Code of goinggo/mapstructure for AI

master 194205d9b4a9 cached
8 files
65.9 KB
19.5k tokens
86 symbols
1 requests
Download .txt
Repository: goinggo/mapstructure
Branch: master
Commit: 194205d9b4a9
Files: 8
Total size: 65.9 KB

Directory structure:
gitextract_pnuccycb/

├── LICENSE
├── README.md
├── error.go
├── mapstructure.go
├── mapstructure_benchmark_test.go
├── mapstructure_bugs_test.go
├── mapstructure_examples_test.go
└── mapstructure_test.go

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 Mitchell Hashimoto, William Kennedy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# mapstructure

mapstructure is a Go library for decoding generic map values to structures
and vice versa, while providing helpful error handling.

This library is most useful when decoding values from some data stream (JSON,
Gob, etc.) where you don't _quite_ know the structure of the underlying data
until you read a part of it. You can therefore read a `map[string]interface{}`
and use this library to decode it into the proper underlying native Go
structure.

## Installation

Standard `go get`:

```
$ go get github.com/goinggo/mapstructure
```

## Usage & Example

For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure).

The `Decode`, `DecodePath` and `DecodeSlicePath` functions have examples associated with it there.

## But Why?!

Go offers fantastic standard libraries for decoding formats such as JSON.
The standard method is to have a struct pre-created, and populate that struct
from the bytes of the encoded format. This is great, but the problem is if
you have configuration or an encoding that changes slightly depending on
specific fields. For example, consider this JSON:

```json
{
  "type": "person",
  "name": "Mitchell"
}
```

Perhaps we can't populate a specific structure without first reading
the "type" field from the JSON. We could always do two passes over the
decoding of the JSON (reading the "type" first, and the rest later).
However, it is much simpler to just decode this into a `map[string]interface{}`
structure, read the "type" key, then use something like this library
to decode it into the proper structure.

## DecodePath

Sometimes you have a large and complex JSON document where you only need to decode
a small part.

```
{
	"userContext": {
		"conversationCredentials": {
	            "sessionToken": "06142010_1:75bf6a413327dd71ebe8f3f30c5a4210a9b11e93c028d6e11abfca7ff"
	    },
	    "valid": true,
	    "isPasswordExpired": false,
	    "cobrandId": 10000004,
	    "channelId": -1,
	    "locale": "en_US",
	    "tncVersion": 2,
	    "applicationId": "17CBE222A42161A3FF450E47CF4C1A00",
	    "cobrandConversationCredentials": {
	        "sessionToken": "06142010_1:b8d011fefbab8bf1753391b074ffedf9578612d676ed2b7f073b5785b"
	    },
	     "preferenceInfo": {
	         "currencyCode": "USD",
	         "timeZone": "PST",
	         "dateFormat": "MM/dd/yyyy",
	         "currencyNotationType": {
	             "currencyNotationType": "SYMBOL"
	         },
	         "numberFormat": {
	             "decimalSeparator": ".",
	             "groupingSeparator": ",",
	             "groupPattern": "###,##0.##"
	         }
	     }
	 },
	 "lastLoginTime": 1375686841,
	 "loginCount": 299,
	 "passwordRecovered": false,
	 "emailAddress": "johndoe@email.com",
	 "loginName": "sptest1",
	 "userId": 10483860,
	 "userType":
	     {
	     "userTypeId": 1,
	     "userTypeName": "normal_user"
	     }
}
```

It is nice to be able to define and pull the documents and fields you need without
having to map the entire JSON structure.

```
type UserType struct {
	UserTypeId   int
	UserTypeName string
}

type NumberFormat struct {
		DecimalSeparator  string `jpath:"userContext.preferenceInfo.numberFormat.decimalSeparator"`
		GroupingSeparator string `jpath:"userContext.preferenceInfo.numberFormat.groupingSeparator"`
		GroupPattern      string `jpath:"userContext.preferenceInfo.numberFormat.groupPattern"`
	}
	
type User struct {
		Session   string   `jpath:"userContext.cobrandConversationCredentials.sessionToken"`
		CobrandId int      `jpath:"userContext.cobrandId"`
		UserType  UserType `jpath:"userType"`
		LoginName string   `jpath:"loginName"`
		NumberFormat       // This can also be a pointer to the struct (*NumberFormat)
}

docScript := []byte(document)
var docMap map[string]interface{}
json.Unmarshal(docScript, &docMap)

var user User
mapstructure.DecodePath(docMap, &user)
```

## DecodeSlicePath

Sometimes you have a slice of documents that you need to decode into a slice of structures

```
[
	{"name":"bill"},
	{"name":"lisa"}
]
```

Just Unmarshal your document into a slice of maps and decode the slice

```
type NameDoc struct {
	Name string `jpath:"name"`
}

sliceScript := []byte(document)
var sliceMap []map[string]interface{}
json.Unmarshal(sliceScript, &sliceMap)

var myslice []NameDoc
err := DecodeSlicePath(sliceMap, &myslice)

var myslice []*NameDoc
err := DecodeSlicePath(sliceMap, &myslice)
```

## Decode Structs With Embedded Slices

Sometimes you have a document with arrays

```
{
	"cobrandId": 10010352,
	"channelId": -1,
	"locale": "en_US",
	"tncVersion": 2,
	"people": [
		{
			"name": "jack",
			"age": {
			"birth":10,
			"year":2000,
			"animals": [
				{
				"barks":"yes",
				"tail":"yes"
				},
				{
				"barks":"no",
				"tail":"yes"
				}
			]
		}
		},
		{
			"name": "jill",
			"age": {
				"birth":11,
				"year":2001
			}
		}
	]
}
```

You can decode within those arrays

```
type Animal struct {
	Barks string `jpath:"barks"`
}

type People struct {
	Age     int      `jpath:"age.birth"` // jpath is relative to the array
	Animals []Animal `jpath:"age.animals"`
}

type Items struct {
	Categories []string `jpath:"categories"`
	Peoples    []People `jpath:"people"` // Specify the location of the array
}

docScript := []byte(document)
var docMap map[string]interface{}
json.Unmarshal(docScript, &docMap)

var items Items
DecodePath(docMap, &items)
```

================================================
FILE: error.go
================================================
package mapstructure

import (
	"fmt"
	"strings"
)

// Error implements the error interface and can represents multiple
// errors that occur in the course of a single decode.
type Error struct {
	Errors []string
}

func (e *Error) Error() string {
	points := make([]string, len(e.Errors))
	for i, err := range e.Errors {
		points[i] = fmt.Sprintf("* %s", err)
	}

	return fmt.Sprintf(
		"%d error(s) decoding:\n\n%s",
		len(e.Errors), strings.Join(points, "\n"))
}

func appendErrors(errors []string, err error) []string {
	switch e := err.(type) {
	case *Error:
		return append(errors, e.Errors...)
	default:
		return append(errors, e.Error())
	}
}


================================================
FILE: mapstructure.go
================================================
// The mapstructure package exposes functionality to convert an
// abitrary map[string]interface{} into a native Go structure.
//
// The Go structure can be arbitrarily complex, containing slices,
// other structs, etc. and the decoder will properly decode nested
// maps and so on into the proper structures in the native Go struct.
// See the examples to see what the decoder is capable of.
package mapstructure

import (
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"
)

type DecodeHookFunc func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)

// DecoderConfig is the configuration that is used to create a new decoder
// and allows customization of various aspects of decoding.
type DecoderConfig struct {
	// DecodeHook, if set, will be called before any decoding and any
	// type conversion (if WeaklyTypedInput is on). This lets you modify
	// the values before they're set down onto the resulting struct.
	//
	// If an error is returned, the entire decode will fail with that
	// error.
	DecodeHook DecodeHookFunc

	// If ErrorUnused is true, then it is an error for there to exist
	// keys in the original map that were unused in the decoding process
	// (extra keys).
	ErrorUnused bool

	// If WeaklyTypedInput is true, the decoder will make the following
	// "weak" conversions:
	//
	//   - bools to string (true = "1", false = "0")
	//   - numbers to string (base 10)
	//   - bools to int/uint (true = 1, false = 0)
	//   - strings to int/uint (base implied by prefix)
	//   - int to bool (true if value != 0)
	//   - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F,
	//     FALSE, false, False. Anything else is an error)
	//   - empty array = empty map and vice versa
	//
	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

	// Result is a pointer to the struct that will contain the decoded
	// value.
	Result interface{}

	// The tag name that mapstructure reads for field names. This
	// defaults to "mapstructure"
	TagName string
}

// A Decoder takes a raw interface value and turns it into structured
// data, keeping track of rich error information along the way in case
// anything goes wrong. Unlike the basic top-level Decode method, you can
// more finely control how the Decoder behaves using the DecoderConfig
// structure. The top-level Decode method is just a convenience that sets
// up the most basic Decoder.
type Decoder struct {
	config *DecoderConfig
}

// Metadata contains information about decoding a structure that
// is tedious or difficult to get otherwise.
type Metadata struct {
	// Keys are the keys of the structure which were successfully decoded
	Keys []string

	// Unused is a slice of keys that were found in the raw value but
	// weren't decoded since there was no matching field in the result interface
	Unused []string
}

// Decode takes a map and uses reflection to convert it into the
// given Go native structure. val must be a pointer to a struct.
func Decode(m interface{}, rawVal interface{}) error {
	config := &DecoderConfig{
		Metadata: nil,
		Result:   rawVal,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		return err
	}

	return decoder.Decode(m)
}

// DecodePath takes a map and uses reflection to convert it into the
// given Go native structure. Tags are used to specify the mapping
// between fields in the map and structure
func DecodePath(m map[string]interface{}, rawVal interface{}) error {
	config := &DecoderConfig{
		Metadata: nil,
		Result:   nil,
	}

	decoder, err := NewPathDecoder(config)
	if err != nil {
		return err
	}

	_, err = decoder.DecodePath(m, rawVal)
	return err
}

// DecodeSlicePath decodes a slice of maps against a slice of structures that
// contain specified tags
func DecodeSlicePath(ms []map[string]interface{}, rawSlice interface{}) error {
	reflectRawSlice := reflect.TypeOf(rawSlice)
	rawKind := reflectRawSlice.Kind()
	rawElement := reflectRawSlice.Elem()

	if (rawKind == reflect.Ptr && rawElement.Kind() != reflect.Slice) ||
		(rawKind != reflect.Ptr && rawKind != reflect.Slice) {
		return fmt.Errorf("Incompatible Value, Looking For Slice : %v : %v", rawKind, rawElement.Kind())
	}

	config := &DecoderConfig{
		Metadata: nil,
		Result:   nil,
	}

	decoder, err := NewPathDecoder(config)
	if err != nil {
		return err
	}

	// Create a slice large enough to decode all the values
	valSlice := reflect.MakeSlice(rawElement, len(ms), len(ms))

	// Iterate over the maps and decode each one
	for index, m := range ms {
		sliceElementType := rawElement.Elem()
		if sliceElementType.Kind() != reflect.Ptr {
			// A slice of objects
			obj := reflect.New(rawElement.Elem())
			decoder.DecodePath(m, reflect.Indirect(obj))
			indexVal := valSlice.Index(index)
			indexVal.Set(reflect.Indirect(obj))
		} else {
			// A slice of pointers
			obj := reflect.New(rawElement.Elem().Elem())
			decoder.DecodePath(m, reflect.Indirect(obj))
			indexVal := valSlice.Index(index)
			indexVal.Set(obj)
		}
	}

	// Set the new slice
	reflect.ValueOf(rawSlice).Elem().Set(valSlice)
	return nil
}

// NewDecoder returns a new decoder for the given configuration. Once
// a decoder has been returned, the same configuration must not be used
// again.
func NewDecoder(config *DecoderConfig) (*Decoder, error) {
	val := reflect.ValueOf(config.Result)
	if val.Kind() != reflect.Ptr {
		return nil, errors.New("result must be a pointer")
	}

	val = val.Elem()
	if !val.CanAddr() {
		return nil, errors.New("result must be addressable (a pointer)")
	}

	if config.Metadata != nil {
		if config.Metadata.Keys == nil {
			config.Metadata.Keys = make([]string, 0)
		}

		if config.Metadata.Unused == nil {
			config.Metadata.Unused = make([]string, 0)
		}
	}

	if config.TagName == "" {
		config.TagName = "mapstructure"
	}

	result := &Decoder{
		config: config,
	}

	return result, nil
}

// NewPathDecoder returns a new decoder for the given configuration.
// This is used to decode path specific structures
func NewPathDecoder(config *DecoderConfig) (*Decoder, error) {
	if config.Metadata != nil {
		if config.Metadata.Keys == nil {
			config.Metadata.Keys = make([]string, 0)
		}

		if config.Metadata.Unused == nil {
			config.Metadata.Unused = make([]string, 0)
		}
	}

	if config.TagName == "" {
		config.TagName = "mapstructure"
	}

	result := &Decoder{
		config: config,
	}

	return result, nil
}

// Decode decodes the given raw interface to the target pointer specified
// by the configuration.
func (d *Decoder) Decode(raw interface{}) error {
	return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem())
}

// DecodePath decodes the raw interface against the map based on the
// specified tags
func (d *Decoder) DecodePath(m map[string]interface{}, rawVal interface{}) (bool, error) {
	decoded := false

	var val reflect.Value
	reflectRawValue := reflect.ValueOf(rawVal)
	kind := reflectRawValue.Kind()

	// Looking for structs and pointers to structs
	switch kind {
	case reflect.Ptr:
		val = reflectRawValue.Elem()
		if val.Kind() != reflect.Struct {
			return decoded, fmt.Errorf("Incompatible Type : %v : Looking For Struct", kind)
		}
	case reflect.Struct:
		var ok bool
		val, ok = rawVal.(reflect.Value)
		if ok == false {
			return decoded, fmt.Errorf("Incompatible Type : %v : Looking For reflect.Value", kind)
		}
	default:
		return decoded, fmt.Errorf("Incompatible Type : %v", kind)
	}

	// Iterate over the fields in the struct
	for i := 0; i < val.NumField(); i++ {
		valueField := val.Field(i)
		typeField := val.Type().Field(i)
		tag := typeField.Tag
		tagValue := tag.Get("jpath")

		// Is this a field without a tag
		if tagValue == "" {
			if valueField.Kind() == reflect.Struct {
				// We have a struct that may have indivdual tags. Process separately
				d.DecodePath(m, valueField)
				continue
			} else if valueField.Kind() == reflect.Ptr && reflect.TypeOf(valueField).Kind() == reflect.Struct {
				// We have a pointer to a struct
				if valueField.IsNil() {
					// Create the object since it doesn't exist
					valueField.Set(reflect.New(valueField.Type().Elem()))
					decoded, _ = d.DecodePath(m, valueField.Elem())
					if decoded == false {
						// If nothing was decoded for this object return the pointer to nil
						valueField.Set(reflect.NewAt(valueField.Type().Elem(), nil))
					}
					continue
				}

				d.DecodePath(m, valueField.Elem())
				continue
			}
		}

		// Use mapstructure to populate the fields
		keys := strings.Split(tagValue, ".")
		data := d.findData(m, keys)
		if data != nil {
			if valueField.Kind() == reflect.Slice {
				// Ignore a slice of maps - This sucks but not sure how to check
				if strings.Contains(valueField.Type().String(), "map[") {
					goto normal_decode
				}

				// We have a slice
				mapSlice := data.([]interface{})
				if len(mapSlice) > 0 {
					// Test if this is a slice of more maps
					_, ok := mapSlice[0].(map[string]interface{})
					if ok == false {
						goto normal_decode
					}

					// Extract the maps out and run it through DecodeSlicePath
					ms := make([]map[string]interface{}, len(mapSlice))
					for index, m2 := range mapSlice {
						ms[index] = m2.(map[string]interface{})
					}

					DecodeSlicePath(ms, valueField.Addr().Interface())
					continue
				}
			}
		normal_decode:
			decoded = true
			err := d.decode("", data, valueField)
			if err != nil {
				return false, err
			}
		}
	}

	return decoded, nil
}

// Decodes an unknown data type into a specific reflection value.
func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error {
	if data == nil {
		// If the data is nil, then we don't set anything.
		return nil
	}

	dataVal := reflect.ValueOf(data)
	if !dataVal.IsValid() {
		// If the data value is invalid, then we just set the value
		// to be the zero value.
		val.Set(reflect.Zero(val.Type()))
		return nil
	}

	if d.config.DecodeHook != nil {
		// We have a DecodeHook, so let's pre-process the data.
		var err error
		data, err = d.config.DecodeHook(d.getKind(dataVal), d.getKind(val), data)
		if err != nil {
			return err
		}
	}

	var err error
	dataKind := d.getKind(val)
	switch dataKind {
	case reflect.Bool:
		err = d.decodeBool(name, data, val)
	case reflect.Interface:
		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:
		err = d.decodeUint(name, data, val)
	case reflect.Float32:
		err = d.decodeFloat(name, data, val)
	case reflect.Struct:
		err = d.decodeStruct(name, data, val)
	case reflect.Map:
		err = d.decodeMap(name, data, val)
	case reflect.Slice:
		err = d.decodeSlice(name, data, val)
	default:
		// If we reached this point then we weren't able to decode it
		return fmt.Errorf("%s: unsupported type: %s", name, dataKind)
	}

	// If we reached here, then we successfully decoded SOMETHING, so
	// mark the key as used if we're tracking metadata.
	if d.config.Metadata != nil && name != "" {
		d.config.Metadata.Keys = append(d.config.Metadata.Keys, name)
	}

	return err
}

// findData locates the data by walking the keys down the map
func (d *Decoder) findData(m map[string]interface{}, keys []string) interface{} {
	if len(keys) == 1 {
		if value, ok := m[keys[0]]; ok == true {
			return value
		}
		return nil
	}

	if value, ok := m[keys[0]]; ok == true {
		if m, ok := value.(map[string]interface{}); ok == true {
			return d.findData(m, keys[1:])
		}
	}

	return nil
}

func (d *Decoder) getKind(val reflect.Value) reflect.Kind {
	kind := val.Kind()

	switch {
	case kind >= reflect.Int && kind <= reflect.Int64:
		return reflect.Int
	case kind >= reflect.Uint && kind <= reflect.Uint64:
		return reflect.Uint
	case kind >= reflect.Float32 && kind <= reflect.Float64:
		return reflect.Float32
	default:
		return kind
	}
}

// This decodes a basic type (bool, int, string, etc.) and sets the
// value to "data" of that type.
func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error {
	dataVal := reflect.ValueOf(data)
	dataValType := dataVal.Type()
	if !dataValType.AssignableTo(val.Type()) {
		return fmt.Errorf(
			"'%s' expected type '%s', got '%s'",
			name, val.Type(), dataValType)
	}

	val.Set(dataVal)
	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 {
	case dataKind == reflect.Int:
		val.SetInt(dataVal.Int())
	case dataKind == reflect.Uint:
		val.SetInt(int64(dataVal.Uint()))
	case dataKind == reflect.Float32:
		val.SetInt(int64(dataVal.Float()))
	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
		if dataVal.Bool() {
			val.SetInt(1)
		} else {
			val.SetInt(0)
		}
	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'",
			name, val.Type(), dataVal.Type())
	}

	return nil
}

func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error {
	dataVal := reflect.ValueOf(data)
	dataKind := d.getKind(dataVal)

	switch {
	case dataKind == reflect.Int:
		val.SetUint(uint64(dataVal.Int()))
	case dataKind == reflect.Uint:
		val.SetUint(dataVal.Uint())
	case dataKind == reflect.Float32:
		val.SetUint(uint64(dataVal.Float()))
	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
		if dataVal.Bool() {
			val.SetUint(1)
		} else {
			val.SetUint(0)
		}
	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'",
			name, val.Type(), dataVal.Type())
	}

	return nil
}

func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error {
	dataVal := reflect.ValueOf(data)
	dataKind := d.getKind(dataVal)

	switch {
	case dataKind == reflect.Int:
		val.SetFloat(float64(dataVal.Int()))
	case dataKind == reflect.Uint:
		val.SetFloat(float64(dataVal.Uint()))
	case dataKind == reflect.Float32:
		val.SetFloat(float64(dataVal.Float()))
	case dataKind == reflect.Bool && d.config.WeaklyTypedInput:
		if dataVal.Bool() {
			val.SetFloat(1)
		} else {
			val.SetFloat(0)
		}
	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'",
			name, val.Type(), dataVal.Type())
	}

	return nil
}

func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error {
	valType := val.Type()
	valKeyType := valType.Key()
	valElemType := valType.Elem()

	// Make a new map to hold our result
	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)

	for _, k := range dataVal.MapKeys() {
		fieldName := fmt.Sprintf("%s[%s]", name, k)

		// First decode the key into the proper type
		currentKey := reflect.Indirect(reflect.New(valKeyType))
		if err := d.decode(fieldName, k.Interface(), currentKey); err != nil {
			errors = appendErrors(errors, err)
			continue
		}

		// Next decode the data into the proper type
		v := dataVal.MapIndex(k).Interface()
		currentVal := reflect.Indirect(reflect.New(valElemType))
		if err := d.decode(fieldName, v, currentVal); err != nil {
			errors = appendErrors(errors, err)
			continue
		}

		valMap.SetMapIndex(currentKey, currentVal)
	}

	// Set the built up map to the value
	val.Set(valMap)

	// If we had errors, return those
	if len(errors) > 0 {
		return &Error{errors}
	}

	return nil
}

func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error {
	dataVal := reflect.Indirect(reflect.ValueOf(data))
	dataValKind := dataVal.Kind()
	valType := val.Type()
	valElemType := valType.Elem()

	// Make a new slice to hold our result, same size as the original data.
	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)

	for i := 0; i < dataVal.Len(); i++ {
		currentData := dataVal.Index(i).Interface()
		currentField := valSlice.Index(i)

		fieldName := fmt.Sprintf("%s[%d]", name, i)
		if err := d.decode(fieldName, currentData, currentField); err != nil {
			errors = appendErrors(errors, err)
		}
	}

	// Finally, set the value to the slice we built up
	val.Set(valSlice)

	// If there were errors, we return those
	if len(errors) > 0 {
		return &Error{errors}
	}

	return nil
}

func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error {
	dataVal := reflect.Indirect(reflect.ValueOf(data))
	dataValKind := dataVal.Kind()
	if dataValKind != reflect.Map {
		return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind)
	}

	dataValType := dataVal.Type()
	if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface {
		return fmt.Errorf(
			"'%s' needs a map with string keys, has '%s' keys",
			name, dataValType.Key().Kind())
	}

	dataValKeys := make(map[reflect.Value]struct{})
	dataValKeysUnused := make(map[interface{}]struct{})
	for _, dataValKey := range dataVal.MapKeys() {
		dataValKeys[dataValKey] = struct{}{}
		dataValKeysUnused[dataValKey.Interface()] = struct{}{}
	}

	errors := make([]string, 0)

	// This slice will keep track of all the structs we'll be decoding.
	// There can be more than one struct if there are embedded structs
	// that are squashed.
	structs := make([]reflect.Value, 1, 5)
	structs[0] = val

	// Compile the list of all the fields that we're going to be decoding
	// from all the structs.
	fields := make(map[*reflect.StructField]reflect.Value)
	for len(structs) > 0 {
		structVal := structs[0]
		structs = structs[1:]

		structType := structVal.Type()
		for i := 0; i < structType.NumField(); i++ {
			fieldType := structType.Field(i)

			if fieldType.Anonymous {
				fieldKind := fieldType.Type.Kind()
				if fieldKind != reflect.Struct {
					errors = appendErrors(errors,
						fmt.Errorf("%s: unsupported type: %s", fieldType.Name, fieldKind))
					continue
				}

				// We have an embedded field. We "squash" the fields down
				// if specified in the tag.
				squash := false
				tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",")
				for _, tag := range tagParts[1:] {
					if tag == "squash" {
						squash = true
						break
					}
				}

				if squash {
					structs = append(structs, val.FieldByName(fieldType.Name))
					continue
				}
			}

			// Normal struct field, store it away
			fields[&fieldType] = structVal.Field(i)
		}
	}

	for fieldType, field := range fields {
		fieldName := fieldType.Name

		tagValue := fieldType.Tag.Get(d.config.TagName)
		tagValue = strings.SplitN(tagValue, ",", 2)[0]
		if tagValue != "" {
			fieldName = tagValue
		}

		rawMapKey := reflect.ValueOf(fieldName)
		rawMapVal := dataVal.MapIndex(rawMapKey)
		if !rawMapVal.IsValid() {
			// Do a slower search by iterating over each key and
			// doing case-insensitive search.
			for dataValKey, _ := range dataValKeys {
				mK, ok := dataValKey.Interface().(string)
				if !ok {
					// Not a string key
					continue
				}

				if strings.EqualFold(mK, fieldName) {
					rawMapKey = dataValKey
					rawMapVal = dataVal.MapIndex(dataValKey)
					break
				}
			}

			if !rawMapVal.IsValid() {
				// There was no matching key in the map for the value in
				// the struct. Just ignore.
				continue
			}
		}

		// Delete the key we're using from the unused map so we stop tracking
		delete(dataValKeysUnused, rawMapKey.Interface())

		if !field.IsValid() {
			// This should never happen
			panic("field is not valid")
		}

		// If we can't set the field, then it is unexported or something,
		// and we just continue onwards.
		if !field.CanSet() {
			continue
		}

		// If the name is empty string, then we're at the root, and we
		// don't dot-join the fields.
		if name != "" {
			fieldName = fmt.Sprintf("%s.%s", name, fieldName)
		}

		if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil {
			errors = appendErrors(errors, err)
		}
	}

	if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
		keys := make([]string, 0, len(dataValKeysUnused))
		for rawKey, _ := range dataValKeysUnused {
			keys = append(keys, rawKey.(string))
		}
		sort.Strings(keys)

		err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", "))
		errors = appendErrors(errors, err)
	}

	if len(errors) > 0 {
		return &Error{errors}
	}

	// Add the unused keys to the list of unused keys if we're tracking metadata
	if d.config.Metadata != nil {
		for rawKey, _ := range dataValKeysUnused {
			key := rawKey.(string)
			if name != "" {
				key = fmt.Sprintf("%s.%s", name, key)
			}

			d.config.Metadata.Unused = append(d.config.Metadata.Unused, key)
		}
	}

	return nil
}


================================================
FILE: mapstructure_benchmark_test.go
================================================
package mapstructure

import (
	"testing"
)

func Benchmark_Decode(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++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeBasic(b *testing.B) {
	input := map[string]interface{}{
		"vstring": "foo",
		"vint":    42,
		"Vuint":   42,
		"vbool":   true,
		"Vfloat":  42.42,
		"vsilent": true,
		"vdata":   42,
	}

	var result Basic
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeEmbedded(b *testing.B) {
	input := map[string]interface{}{
		"vstring": "foo",
		"Basic": map[string]interface{}{
			"vstring": "innerfoo",
		},
		"vunique": "bar",
	}

	var result Embedded
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeTypeConversion(b *testing.B) {
	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{}{},
	}

	var resultStrict TypeConversionResult
	for i := 0; i < b.N; i++ {
		Decode(input, &resultStrict)
	}
}

func Benchmark_DecodeMap(b *testing.B) {
	input := map[string]interface{}{
		"vfoo": "foo",
		"vother": map[interface{}]interface{}{
			"foo": "foo",
			"bar": "bar",
		},
	}

	var result Map
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeMapOfStruct(b *testing.B) {
	input := map[string]interface{}{
		"value": map[string]interface{}{
			"foo": map[string]string{"vstring": "one"},
			"bar": map[string]string{"vstring": "two"},
		},
	}

	var result MapOfStruct
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeSlice(b *testing.B) {
	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": []string{"foo", "bar", "baz"},
	}

	var result Slice
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeSliceOfStruct(b *testing.B) {
	input := map[string]interface{}{
		"value": []map[string]interface{}{
			{"vstring": "one"},
			{"vstring": "two"},
		},
	}

	var result SliceOfStruct
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}

func Benchmark_DecodeWeaklyTypedInput(b *testing.B) {
	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)
	}

	for i := 0; i < b.N; i++ {
		decoder.Decode(input)
	}
}

func Benchmark_DecodeMetadata(b *testing.B) {
	type Person struct {
		Name string
		Age  int
	}

	input := map[string]interface{}{
		"name":  "Mitchell",
		"age":   91,
		"email": "foo@bar.com",
	}

	var md Metadata
	var result Person
	config := &DecoderConfig{
		Metadata: &md,
		Result:   &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		panic(err)
	}

	for i := 0; i < b.N; i++ {
		decoder.Decode(input)
	}
}

func Benchmark_DecodeMetadataEmbedded(b *testing.B) {
	input := map[string]interface{}{
		"vstring": "foo",
		"vunique": "bar",
	}

	var md Metadata
	var result EmbeddedSquash
	config := &DecoderConfig{
		Metadata: &md,
		Result:   &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		b.Fatalf("err: %s", err)
	}

	for i := 0; i < b.N; i++ {
		decoder.Decode(input)
	}
}

func Benchmark_DecodeTagged(b *testing.B) {
	input := map[string]interface{}{
		"foo": "bar",
		"bar": "value",
	}

	var result Tagged
	for i := 0; i < b.N; i++ {
		Decode(input, &result)
	}
}


================================================
FILE: mapstructure_bugs_test.go
================================================
package mapstructure

import "testing"

// GH-1
func TestDecode_NilValue(t *testing.T) {
	input := map[string]interface{}{
		"vfoo":   nil,
		"vother": nil,
	}

	var result Map
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("should not error: %s", err)
	}

	if result.Vfoo != "" {
		t.Fatalf("value should be default: %s", result.Vfoo)
	}

	if result.Vother != nil {
		t.Fatalf("Vother should be nil: %s", result.Vother)
	}
}

// GH-10
func TestDecode_mapInterfaceInterface(t *testing.T) {
	input := map[interface{}]interface{}{
		"vfoo":   nil,
		"vother": nil,
	}

	var result Map
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("should not error: %s", err)
	}

	if result.Vfoo != "" {
		t.Fatalf("value should be default: %s", result.Vfoo)
	}

	if result.Vother != nil {
		t.Fatalf("Vother should be nil: %s", result.Vother)
	}
}


================================================
FILE: mapstructure_examples_test.go
================================================
package mapstructure

import (
	"encoding/json"
	"fmt"
)

func ExampleDecode() {
	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 := Decode(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
		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":   123,
		"age":    "bad value",
		"emails": []int{1, 2, 3},
	}

	var result Person
	err := Decode(input, &result)
	if err == nil {
		panic("should have an error")
	}

	fmt.Println(err.Error())
	// Output:
	// 5 error(s) decoding:
	//
	// * 'Name' expected type 'string', got unconvertible type 'int'
	// * 'Age' expected type 'int', got unconvertible type 'string'
	// * '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() {
	type Person struct {
		Name string
		Age  int
	}

	// 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,
		"email": "foo@bar.com",
	}

	// For metadata, we make a more advanced DecoderConfig so we can
	// more finely configure the decoder that is used. In this case, we
	// just tell the decoder we want to track metadata.
	var md Metadata
	var result Person
	config := &DecoderConfig{
		Metadata: &md,
		Result:   &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		panic(err)
	}

	if err := decoder.Decode(input); err != nil {
		panic(err)
	}

	fmt.Printf("Unused keys: %#v", md.Unused)
	// 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{}}
}

func ExampleDecodePath() {
	var document string = `{
    "userContext": {
        "conversationCredentials": {
            "sessionToken": "06142010_1:75bf6a413327dd71ebe8f3f30c5a4210a9b11e93c028d6e11abfca7ff"
        },
        "valid": true,
        "isPasswordExpired": false,
        "cobrandId": 10000004,
        "channelId": -1,
        "locale": "en_US",
        "tncVersion": 2,
        "applicationId": "17CBE222A42161A3FF450E47CF4C1A00",
        "cobrandConversationCredentials": {
            "sessionToken": "06142010_1:b8d011fefbab8bf1753391b074ffedf9578612d676ed2b7f073b5785b"
        },
        "preferenceInfo": {
            "currencyCode": "USD",
            "timeZone": "PST",
            "dateFormat": "MM/dd/yyyy",
            "currencyNotationType": {
                "currencyNotationType": "SYMBOL"
            },
            "numberFormat": {
                "decimalSeparator": ".",
                "groupingSeparator": ",",
                "groupPattern": "###,##0.##"
            }
        }
    },
    "lastLoginTime": 1375686841,
    "loginCount": 299,
    "passwordRecovered": false,
    "emailAddress": "johndoe@email.com",
    "loginName": "sptest1",
    "userId": 10483860,
    "userType":
        {
        "userTypeId": 1,
        "userTypeName": "normal_user"
        }
}`

	type UserType struct {
		UserTypeId   int
		UserTypeName string
	}

	type NumberFormat struct {
		DecimalSeparator  string `jpath:"userContext.preferenceInfo.numberFormat.decimalSeparator"`
		GroupingSeparator string `jpath:"userContext.preferenceInfo.numberFormat.groupingSeparator"`
		GroupPattern      string `jpath:"userContext.preferenceInfo.numberFormat.groupPattern"`
	}

	type User struct {
		Session      string   `jpath:"userContext.cobrandConversationCredentials.sessionToken"`
		CobrandId    int      `jpath:"userContext.cobrandId"`
		UserType     UserType `jpath:"userType"`
		LoginName    string   `jpath:"loginName"`
		NumberFormat          // This can also be a pointer to the struct (*NumberFormat)
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	var user User
	DecodePath(docMap, &user)

	fmt.Printf("%#v", user)
	// Output:
	// mapstructure.User{Session:"06142010_1:b8d011fefbab8bf1753391b074ffedf9578612d676ed2b7f073b5785b", CobrandId:10000004, UserType:mapstructure.UserType{UserTypeId:1, UserTypeName:"normal_user"}, LoginName:"sptest1", NumberFormat:mapstructure.NumberFormat{DecimalSeparator:".", GroupingSeparator:",", GroupPattern:"###,##0.##"}}
}

func ExampleDecodeSlicePath() {
	var document = `[{"name":"bill"},{"name":"lisa"}]`

	type NameDoc struct {
		Name string `jpath:"name"`
	}

	sliceScript := []byte(document)
	var sliceMap []map[string]interface{}
	json.Unmarshal(sliceScript, &sliceMap)

	var myslice []NameDoc
	DecodeSlicePath(sliceMap, &myslice)

	fmt.Printf("%#v", myslice)
	// Output:
	// []mapstructure.NameDoc{mapstructure.NameDoc{Name:"bill"}, mapstructure.NameDoc{Name:"lisa"}}
}

func ExampleDecodeWithEmbeddedSlice() {
	var document string = `{
	  "cobrandId": 10010352,
	  "channelId": -1,
	  "locale": "en_US",
	  "tncVersion": 2,
	  "categories":["rabbit","bunny","frog"],
	  "people": [
	 	{
			"name": "jack",
			"age": {
				"birth":10,
				"year":2000,
				"animals": [
					{
						"barks":"yes",
						"tail":"yes"
					},
					{
						"barks":"no",
						"tail":"yes"
					}
				]
			}
		},
		{
			"name": "jill",
			"age": {
				"birth":11,
				"year":2001
			}
		}
	  ]
}`

	type Animal struct {
		Barks string `jpath:"barks"`
	}

	type People struct {
		Age     int      `jpath:"age.birth"` // jpath is relative to the array
		Animals []Animal `jpath:"age.animals"`
	}

	type Items struct {
		Categories []string `jpath:"categories"`
		Peoples    []People `jpath:"people"` // Specify the location of the array
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	var items Items
	DecodePath(docMap, &items)

	fmt.Printf("%#v", items)
	// Output:
	// mapstructure.Items{Categories:[]string{"rabbit", "bunny", "frog"}, Peoples:[]mapstructure.People{mapstructure.People{Age:10, Animals:[]mapstructure.Animal{mapstructure.Animal{Barks:"yes"}, mapstructure.Animal{Barks:"no"}}}, mapstructure.People{Age:11, Animals:[]mapstructure.Animal(nil)}}}
}

func ExampleDecodeWithAbstractField() {
	var document = `{"Error":[{"errorDetail":"Invalid Cobrand Credentials"}]}`

	type YodleeError struct {
		Error []map[string]interface{} `jpath:"Error"`
	}

	type CobrandContext struct {
		YodleeError
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	var cobrandContext CobrandContext
	DecodePath(docMap, &cobrandContext)

	fmt.Printf("%#v", cobrandContext)
	// Output:
	// mapstructure.CobrandContext{YodleeError:mapstructure.YodleeError{Error:[]map[string]interface {}{map[string]interface {}{"errorDetail":"Invalid Cobrand Credentials"}}}}
}


================================================
FILE: mapstructure_test.go
================================================
package mapstructure

import (
	"encoding/json"
	"reflect"
	"sort"
	"testing"
)

type Basic struct {
	Vstring string
	Vint    int
	Vuint   uint
	Vbool   bool
	Vfloat  float64
	Vextra  string
	vsilent bool
	Vdata   interface{}
}

type Embedded struct {
	Basic
	Vunique string
}

type EmbeddedPointer struct {
	*Basic
	Vunique string
}

type EmbeddedSquash struct {
	Basic   `mapstructure:",squash"`
	Vunique string
}

type Map struct {
	Vfoo   string
	Vother map[string]string
}

type MapOfStruct struct {
	Value map[string]Basic
}

type Nested struct {
	Vfoo string
	Vbar Basic
}

type Slice struct {
	Vfoo string
	Vbar []string
}

type SliceOfStruct struct {
	Value []Basic
}

type Tagged struct {
	Extra string `mapstructure:"bar,what,what"`
	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()

	input := map[string]interface{}{
		"vstring": "foo",
		"vint":    42,
		"Vuint":   42,
		"vbool":   true,
		"Vfloat":  42.42,
		"vsilent": true,
		"vdata":   42,
	}

	var result Basic
	err := Decode(input, &result)
	if err != nil {
		t.Errorf("got an err: %s", err.Error())
		t.FailNow()
	}

	if result.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
	}

	if result.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vint)
	}

	if result.Vuint != 42 {
		t.Errorf("vuint value should be 42: %#v", result.Vuint)
	}

	if result.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbool)
	}

	if result.Vfloat != 42.42 {
		t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat)
	}

	if result.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vextra)
	}

	if result.vsilent != false {
		t.Error("vsilent should not be set, it is unexported")
	}

	if result.Vdata != 42 {
		t.Error("vdata should be valid")
	}
}

func TestBasic_IntWithFloat(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vint": float64(42),
	}

	var result Basic
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err)
	}
}

func TestDecode_Embedded(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": "foo",
		"Basic": map[string]interface{}{
			"vstring": "innerfoo",
		},
		"vunique": "bar",
	}

	var result Embedded
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vstring != "innerfoo" {
		t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring)
	}

	if result.Vunique != "bar" {
		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
	}
}

func TestDecode_EmbeddedPointer(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": "foo",
		"Basic": map[string]interface{}{
			"vstring": "innerfoo",
		},
		"vunique": "bar",
	}

	var result EmbeddedPointer
	err := Decode(input, &result)
	if err == nil {
		t.Fatal("should get error")
	}
}

func TestDecode_EmbeddedSquash(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": "foo",
		"vunique": "bar",
	}

	var result EmbeddedSquash
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vstring)
	}

	if result.Vunique != "bar" {
		t.Errorf("vunique value should be 'bar': %#v", result.Vunique)
	}
}

func TestDecode_DecodeHook(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vint": "WHAT",
	}

	decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) {
		if from == reflect.String && to != reflect.String {
			return 5, nil
		}

		return v, nil
	}

	var result Basic
	config := &DecoderConfig{
		DecodeHook: decodeHook,
		Result:     &result,
	}

	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 result.Vint != 5 {
		t.Errorf("vint should be 5: %#v", result.Vint)
	}
}

func TestDecode_Nil(t *testing.T) {
	t.Parallel()

	var input interface{} = nil
	result := Basic{
		Vstring: "foo",
	}

	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if result.Vstring != "foo" {
		t.Fatalf("bad: %#v", result.Vstring)
	}
}

func TestDecode_NonStruct(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"foo": "bar",
		"bar": "baz",
	}

	var result map[string]string
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if result["foo"] != "bar" {
		t.Fatal("foo is not bar")
	}
}

func TestDecode_TypeConversion(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 TestDecoder_ErrorUnused(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": "hello",
		"foo":     "bar",
	}

	var result Basic
	config := &DecoderConfig{
		ErrorUnused: true,
		Result:      &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = decoder.Decode(input)
	if err == nil {
		t.Fatal("expected error")
	}
}

func TestMap(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vother": map[interface{}]interface{}{
			"foo": "foo",
			"bar": "bar",
		},
	}

	var result Map
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an error: %s", err)
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vother == nil {
		t.Fatal("vother should not be nil")
	}

	if len(result.Vother) != 2 {
		t.Error("vother should have two items")
	}

	if result.Vother["foo"] != "foo" {
		t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"])
	}

	if result.Vother["bar"] != "bar" {
		t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"])
	}
}

func TestMapOfStruct(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"value": map[string]interface{}{
			"foo": map[string]string{"vstring": "one"},
			"bar": map[string]string{"vstring": "two"},
		},
	}

	var result MapOfStruct
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err)
	}

	if result.Value == nil {
		t.Fatal("value should not be nil")
	}

	if len(result.Value) != 2 {
		t.Error("value should have two items")
	}

	if result.Value["foo"].Vstring != "one" {
		t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring)
	}

	if result.Value["bar"].Vstring != "two" {
		t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring)
	}
}

func TestNestedType(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	var result Nested
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}
}

func TestNestedTypePointer(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": &map[string]interface{}{
			"vstring": "foo",
			"vint":    42,
			"vbool":   true,
		},
	}

	var result Nested
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got an err: %s", err.Error())
	}

	if result.Vfoo != "foo" {
		t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo)
	}

	if result.Vbar.Vstring != "foo" {
		t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring)
	}

	if result.Vbar.Vint != 42 {
		t.Errorf("vint value should be 42: %#v", result.Vbar.Vint)
	}

	if result.Vbar.Vbool != true {
		t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool)
	}

	if result.Vbar.Vextra != "" {
		t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra)
	}
}

func TestSlice(t *testing.T) {
	t.Parallel()

	inputStringSlice := map[string]interface{}{
		"vfoo": "foo",
		"vbar": []string{"foo", "bar", "baz"},
	}

	inputStringSlicePointer := map[string]interface{}{
		"vfoo": "foo",
		"vbar": &[]string{"foo", "bar", "baz"},
	}

	outputStringSlice := &Slice{
		"foo",
		[]string{"foo", "bar", "baz"},
	}

	testSliceInput(t, inputStringSlice, outputStringSlice)
	testSliceInput(t, inputStringSlicePointer, outputStringSlice)
}

func TestSliceOfStruct(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"value": []map[string]interface{}{
			{"vstring": "one"},
			{"vstring": "two"},
		},
	}

	var result SliceOfStruct
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got unexpected error: %s", err)
	}

	if len(result.Value) != 2 {
		t.Fatalf("expected two values, got %d", len(result.Value))
	}

	if result.Value[0].Vstring != "one" {
		t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring)
	}

	if result.Value[1].Vstring != "two" {
		t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring)
	}
}

func TestInvalidType(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": 42,
	}

	var result Basic
	err := Decode(input, &result)
	if err == nil {
		t.Fatal("error should exist")
	}

	derr, ok := err.(*Error)
	if !ok {
		t.Fatalf("error should be kind of Error, instead: %#v", err)
	}

	if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" {
		t.Errorf("got unexpected error: %s", err)
	}
}

func TestMetadata(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vfoo": "foo",
		"vbar": map[string]interface{}{
			"vstring": "foo",
			"Vuint":   42,
			"foo":     "bar",
		},
		"bar": "nil",
	}

	var md Metadata
	var result Nested
	config := &DecoderConfig{
		Metadata: &md,
		Result:   &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = decoder.Decode(input)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	expectedKeys := []string{"Vfoo", "Vbar.Vstring", "Vbar.Vuint", "Vbar"}
	if !reflect.DeepEqual(md.Keys, expectedKeys) {
		t.Fatalf("bad keys: %#v", md.Keys)
	}

	expectedUnused := []string{"Vbar.foo", "bar"}
	if !reflect.DeepEqual(md.Unused, expectedUnused) {
		t.Fatalf("bad unused: %#v", md.Unused)
	}
}

func TestMetadata_Embedded(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"vstring": "foo",
		"vunique": "bar",
	}

	var md Metadata
	var result EmbeddedSquash
	config := &DecoderConfig{
		Metadata: &md,
		Result:   &result,
	}

	decoder, err := NewDecoder(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	err = decoder.Decode(input)
	if err != nil {
		t.Fatalf("err: %s", err.Error())
	}

	expectedKeys := []string{"Vstring", "Vunique"}

	sort.Strings(md.Keys)
	if !reflect.DeepEqual(md.Keys, expectedKeys) {
		t.Fatalf("bad keys: %#v", md.Keys)
	}

	expectedUnused := []string{}
	if !reflect.DeepEqual(md.Unused, expectedUnused) {
		t.Fatalf("bad unused: %#v", md.Unused)
	}
}

func TestNonPtrValue(t *testing.T) {
	t.Parallel()

	err := Decode(map[string]interface{}{}, Basic{})
	if err == nil {
		t.Fatal("error should exist")
	}

	if err.Error() != "result must be a pointer" {
		t.Errorf("got unexpected error: %s", err)
	}
}

func TestTagged(t *testing.T) {
	t.Parallel()

	input := map[string]interface{}{
		"foo": "bar",
		"bar": "value",
	}

	var result Tagged
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}

	if result.Value != "bar" {
		t.Errorf("value should be 'bar', got: %#v", result.Value)
	}

	if result.Extra != "value" {
		t.Errorf("extra should be 'value', got: %#v", result.Extra)
	}
}

func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) {
	var result Slice
	err := Decode(input, &result)
	if err != nil {
		t.Fatalf("got error: %s", err)
	}

	if result.Vfoo != expected.Vfoo {
		t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo)
	}

	if result.Vbar == nil {
		t.Fatalf("Vbar a slice, got '%#v'", result.Vbar)
	}

	if len(result.Vbar) != len(expected.Vbar) {
		t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar))
	}

	for i, v := range result.Vbar {
		if v != expected.Vbar[i] {
			t.Errorf(
				"Vbar[%d] should be '%#v', got '%#v'",
				i, expected.Vbar[i], v)
		}
	}
}

func TestDecodePath(t *testing.T) {
	var document string = `{
    "userContext": {
        "cobrandId": 10000004,
        "channelId": -1,
        "locale": "en_US",
        "tncVersion": 2,
        "applicationId": "17CBE222A42161A3FF450E47CF4C1A00",
        "cobrandConversationCredentials": {
            "sessionToken": "06142010_1:b8d011fefbab8bf1753391b074ffedf9578612d676ed2b7f073b5785b"
        },
		"preferenceInfo": {
            "currencyCode": "USD",
            "timeZone": "PST",
            "dateFormat": "MM/dd/yyyy",
            "currencyNotationType": {
                "currencyNotationType": "SYMBOL"
            },
            "numberFormat": {
                "decimalSeparator": ".",
                "groupingSeparator": ",",
                "groupPattern": "###,##0.##"
            }
        }
    },
    "loginName": "sptest1",
    "userId": 10483860,
    "userType":
        {
        "userTypeId": 1,
        "userTypeName": "normal_user"
        }
}`

	type UserType struct {
		UserTypeId   int
		UserTypeName string
	}

	type NumberFormat struct {
		DecimalSeparator  string `jpath:"userContext.preferenceInfo.numberFormat.decimalSeparator"`
		GroupingSeparator string `jpath:"userContext.preferenceInfo.numberFormat.groupingSeparator"`
		GroupPattern      string `jpath:"userContext.preferenceInfo.numberFormat.groupPattern"`
	}

	type User struct {
		Session   string   `jpath:"userContext.cobrandConversationCredentials.sessionToken"`
		CobrandId int      `jpath:"userContext.cobrandId"`
		UserType  UserType `jpath:"userType"`
		LoginName string   `jpath:"loginName"`
		*NumberFormat
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	err := json.Unmarshal(docScript, &docMap)
	if err != nil {
		t.Fatalf("Unable To Unmarshal Test Document, %s", err)
	}

	var user User
	DecodePath(docMap, &user)

	session := "06142010_1:b8d011fefbab8bf1753391b074ffedf9578612d676ed2b7f073b5785b"
	if user.Session != session {
		t.Errorf("user.Session should be '%s', we got '%s'", session, user.Session)
	}

	cobrandId := 10000004
	if user.CobrandId != cobrandId {
		t.Errorf("user.CobrandId should be '%d', we got '%d'", cobrandId, user.CobrandId)
	}

	loginName := "sptest1"
	if user.LoginName != loginName {
		t.Errorf("user.LoginName should be '%s', we got '%s'", loginName, user.LoginName)
	}

	userTypeId := 1
	if user.UserType.UserTypeId != userTypeId {
		t.Errorf("user.UserType.UserTypeId should be '%d', we got '%d'", userTypeId, user.UserType.UserTypeId)
	}

	userTypeName := "normal_user"
	if user.UserType.UserTypeName != userTypeName {
		t.Errorf("user.UserType.UserTypeName should be '%s', we got '%s'", userTypeName, user.UserType.UserTypeName)
	}

	decimalSeparator := "."
	if user.NumberFormat.DecimalSeparator != decimalSeparator {
		t.Errorf("user.NumberFormat.DecimalSeparator should be '%s', we got '%s'", decimalSeparator, user.NumberFormat.DecimalSeparator)
	}

	groupingSeparator := ","
	if user.NumberFormat.GroupingSeparator != groupingSeparator {
		t.Errorf("user.NumberFormat.GroupingSeparator should be '%s', we got '%s'", groupingSeparator, user.NumberFormat.GroupingSeparator)
	}

	groupPattern := "###,##0.##"
	if user.NumberFormat.GroupPattern != groupPattern {
		t.Errorf("user.NumberFormat.GroupPattern should be '%s', we got '%s'", groupPattern, user.NumberFormat.GroupPattern)
	}
}

func TestDecodeSlicePath(t *testing.T) {
	var document = `[{"name":"bill"},{"name":"lisa"}]`

	type NameDoc struct {
		Name string `jpath:"name"`
	}

	sliceScript := []byte(document)
	var sliceMap []map[string]interface{}
	json.Unmarshal(sliceScript, &sliceMap)

	var myslice1 []NameDoc
	err1 := DecodeSlicePath(sliceMap, &myslice1)

	var myslice2 []*NameDoc
	err2 := DecodeSlicePath(sliceMap, &myslice2)

	name1 := "bill"
	name2 := "lisa"

	if err1 != nil {
		t.Fatal(err1)
	}

	if err2 != nil {
		t.Fatal(err1)
	}

	if myslice1[0].Name != name1 {
		t.Errorf("myslice1[0].Name should be '%s', we got '%s'", name1, myslice1[0].Name)
	}

	if myslice1[1].Name != name2 {
		t.Errorf("myslice1[1].Name should be '%s', we got '%s'", name1, myslice1[1].Name)
	}

	if myslice2[0].Name != name1 {
		t.Errorf("myslice2[0].Name should be '%s', we got '%s'", name1, myslice1[0].Name)
	}

	if myslice2[1].Name != name2 {
		t.Errorf("myslice1[1].Name should be '%s', we got '%s'", name2, myslice2[1].Name)
	}
}

func TestDecodeWithEmbeddedSlice(t *testing.T) {
	var document string = `{
		"cobrandId": 10010352,
		"channelId": -1,
		"locale": "en_US",
		"tncVersion": 2,
		"categories":["rabbit","bunny","frog"],
		"people": [
			{
				"name": "jack",
				"age": {
				"birth":10,
				"year":2000,
				"animals": [
					{
					"barks":"yes",
					"tail":"yes"
					},
					{
					"barks":"no",
					"tail":"yes"
					}
				]
			}
			},
			{
				"name": "jill",
				"age": {
					"birth":11,
					"year":2001
				}
			}
		]
}`

	type Animal struct {
		Barks string `jpath:"barks"`
	}

	type People struct {
		Age     int      `jpath:"age.birth"`
		Animals []Animal `jpath:"age.animals"`
	}

	type Items struct {
		Categories []string `jpath:"categories"`
		Peoples    []People `jpath:"people"`
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	items := Items{}
	DecodePath(docMap, &items)

	if len(items.Categories) != 3 {
		t.Error("items.Categories did not decode")
		return
	}

	if len(items.Peoples) != 2 {
		t.Error("items.Peoples did not decode")
		return
	}

	if len(items.Peoples[0].Animals) != 2 {
		t.Error("items.Peoples[0].Animals did not decode")
		return
	}

	age := 10
	if items.Peoples[0].Age != 10 {
		t.Errorf("items.Peoples[0].Age should be '%d', we got '%s'", age, items.Peoples[0].Age)
	}

	barks := "yes"
	if items.Peoples[0].Animals[0].Barks != barks {
		t.Errorf("items.Peoples[0].Animals[0].Barks should be '%d', we got '%s'", barks, items.Peoples[0].Animals[0].Barks)
	}
}

func TestDecodeWithAbstractField(t *testing.T) {
	var document = `{"Error":[{"errorDetail":"Invalid Cobrand Credentials"}]}`

	type AnError struct {
		Error []map[string]interface{} `jpath:"Error"`
	}

	type Context struct {
		*AnError
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	context := Context{}
	DecodePath(docMap, &context)

	errorDetail := "Invalid Cobrand Credentials"
	if context.Error[0]["errorDetail"].(string) != errorDetail {
		t.Errorf("context.Error[0][\"errorDetail\"] should be '%s', we got '%s'", errorDetail, context.Error[0]["errorDetail"].(string))
	}
}

func TestDecodePointerToPointer(t *testing.T) {
	var document = `{"Error":[{"errorDetail":"Invalid Cobrand Credentials"}]}`

	type AnError struct {
		Error []map[string]interface{} `jpath:"Error"`
	}

	type APointerError struct {
		*AnError
	}

	type Context struct {
		*APointerError
	}

	docScript := []byte(document)
	var docMap map[string]interface{}
	json.Unmarshal(docScript, &docMap)

	var context Context
	DecodePath(docMap, &context)

	errorDetail := "Invalid Cobrand Credentials"
	if context.Error != nil {
		if context.Error[0]["errorDetail"].(string) != errorDetail {
			t.Errorf("context.Error[0][\"errorDetail\"] should be '%s', we got '%s'", errorDetail, context.Error[0]["errorDetail"].(string))
		}
	}
}
Download .txt
gitextract_pnuccycb/

├── LICENSE
├── README.md
├── error.go
├── mapstructure.go
├── mapstructure_benchmark_test.go
├── mapstructure_bugs_test.go
├── mapstructure_examples_test.go
└── mapstructure_test.go
Download .txt
SYMBOL INDEX (86 symbols across 6 files)

FILE: error.go
  type Error (line 10) | type Error struct
    method Error (line 14) | func (e *Error) Error() string {
  function appendErrors (line 25) | func appendErrors(errors []string, err error) []string {

FILE: mapstructure.go
  type DecodeHookFunc (line 19) | type DecodeHookFunc
  type DecoderConfig (line 23) | type DecoderConfig struct
  type Decoder (line 70) | type Decoder struct
    method Decode (line 228) | func (d *Decoder) Decode(raw interface{}) error {
    method DecodePath (line 234) | func (d *Decoder) DecodePath(m map[string]interface{}, rawVal interfac...
    method decode (line 331) | func (d *Decoder) decode(name string, data interface{}, val reflect.Va...
    method findData (line 390) | func (d *Decoder) findData(m map[string]interface{}, keys []string) in...
    method getKind (line 407) | func (d *Decoder) getKind(val reflect.Value) reflect.Kind {
    method decodeBasic (line 424) | func (d *Decoder) decodeBasic(name string, data interface{}, val refle...
    method decodeString (line 437) | func (d *Decoder) decodeString(name string, data interface{}, val refl...
    method decodeInt (line 465) | func (d *Decoder) decodeInt(name string, data interface{}, val reflect...
    method decodeUint (line 498) | func (d *Decoder) decodeUint(name string, data interface{}, val reflec...
    method decodeBool (line 531) | func (d *Decoder) decodeBool(name string, data interface{}, val reflec...
    method decodeFloat (line 562) | func (d *Decoder) decodeFloat(name string, data interface{}, val refle...
    method decodeMap (line 595) | func (d *Decoder) decodeMap(name string, data interface{}, val reflect...
    method decodeSlice (line 653) | func (d *Decoder) decodeSlice(name string, data interface{}, val refle...
    method decodeStruct (line 699) | func (d *Decoder) decodeStruct(name string, data interface{}, val refl...
  type Metadata (line 76) | type Metadata struct
  function Decode (line 87) | func Decode(m interface{}, rawVal interface{}) error {
  function DecodePath (line 104) | func DecodePath(m map[string]interface{}, rawVal interface{}) error {
  function DecodeSlicePath (line 121) | func DecodeSlicePath(ms []map[string]interface{}, rawSlice interface{}) ...
  function NewDecoder (line 170) | func NewDecoder(config *DecoderConfig) (*Decoder, error) {
  function NewPathDecoder (line 204) | func NewPathDecoder(config *DecoderConfig) (*Decoder, error) {

FILE: mapstructure_benchmark_test.go
  function Benchmark_Decode (line 7) | func Benchmark_Decode(b *testing.B) {
  function Benchmark_DecodeBasic (line 30) | func Benchmark_DecodeBasic(b *testing.B) {
  function Benchmark_DecodeEmbedded (line 47) | func Benchmark_DecodeEmbedded(b *testing.B) {
  function Benchmark_DecodeTypeConversion (line 62) | func Benchmark_DecodeTypeConversion(b *testing.B) {
  function Benchmark_DecodeMap (line 94) | func Benchmark_DecodeMap(b *testing.B) {
  function Benchmark_DecodeMapOfStruct (line 109) | func Benchmark_DecodeMapOfStruct(b *testing.B) {
  function Benchmark_DecodeSlice (line 123) | func Benchmark_DecodeSlice(b *testing.B) {
  function Benchmark_DecodeSliceOfStruct (line 135) | func Benchmark_DecodeSliceOfStruct(b *testing.B) {
  function Benchmark_DecodeWeaklyTypedInput (line 149) | func Benchmark_DecodeWeaklyTypedInput(b *testing.B) {
  function Benchmark_DecodeMetadata (line 181) | func Benchmark_DecodeMetadata(b *testing.B) {
  function Benchmark_DecodeMetadataEmbedded (line 210) | func Benchmark_DecodeMetadataEmbedded(b *testing.B) {
  function Benchmark_DecodeTagged (line 233) | func Benchmark_DecodeTagged(b *testing.B) {

FILE: mapstructure_bugs_test.go
  function TestDecode_NilValue (line 6) | func TestDecode_NilValue(t *testing.T) {
  function TestDecode_mapInterfaceInterface (line 28) | func TestDecode_mapInterfaceInterface(t *testing.T) {

FILE: mapstructure_examples_test.go
  function ExampleDecode (line 8) | func ExampleDecode() {
  function ExampleDecode_errors (line 39) | func ExampleDecode_errors() {
  function ExampleDecode_metadata (line 73) | func ExampleDecode_metadata() {
  function ExampleDecode_weaklyTypedInput (line 112) | func ExampleDecode_weaklyTypedInput() {
  function ExampleDecodePath (line 148) | func ExampleDecodePath() {
  function ExampleDecodeSlicePath (line 222) | func ExampleDecodeSlicePath() {
  function ExampleDecodeWithEmbeddedSlice (line 241) | func ExampleDecodeWithEmbeddedSlice() {
  function ExampleDecodeWithAbstractField (line 302) | func ExampleDecodeWithAbstractField() {

FILE: mapstructure_test.go
  type Basic (line 10) | type Basic struct
  type Embedded (line 21) | type Embedded struct
  type EmbeddedPointer (line 26) | type EmbeddedPointer struct
  type EmbeddedSquash (line 31) | type EmbeddedSquash struct
  type Map (line 36) | type Map struct
  type MapOfStruct (line 41) | type MapOfStruct struct
  type Nested (line 45) | type Nested struct
  type Slice (line 50) | type Slice struct
  type SliceOfStruct (line 55) | type SliceOfStruct struct
  type Tagged (line 59) | type Tagged struct
  type TypeConversionResult (line 64) | type TypeConversionResult struct
  function TestBasicTypes (line 89) | func TestBasicTypes(t *testing.T) {
  function TestBasic_IntWithFloat (line 142) | func TestBasic_IntWithFloat(t *testing.T) {
  function TestDecode_Embedded (line 156) | func TestDecode_Embedded(t *testing.T) {
  function TestDecode_EmbeddedPointer (line 182) | func TestDecode_EmbeddedPointer(t *testing.T) {
  function TestDecode_EmbeddedSquash (line 200) | func TestDecode_EmbeddedSquash(t *testing.T) {
  function TestDecode_DecodeHook (line 223) | func TestDecode_DecodeHook(t *testing.T) {
  function TestDecode_Nil (line 259) | func TestDecode_Nil(t *testing.T) {
  function TestDecode_NonStruct (line 277) | func TestDecode_NonStruct(t *testing.T) {
  function TestDecode_TypeConversion (line 296) | func TestDecode_TypeConversion(t *testing.T) {
  function TestDecoder_ErrorUnused (line 393) | func TestDecoder_ErrorUnused(t *testing.T) {
  function TestMap (line 418) | func TestMap(t *testing.T) {
  function TestMapOfStruct (line 456) | func TestMapOfStruct(t *testing.T) {
  function TestNestedType (line 489) | func TestNestedType(t *testing.T) {
  function TestNestedTypePointer (line 528) | func TestNestedTypePointer(t *testing.T) {
  function TestSlice (line 567) | func TestSlice(t *testing.T) {
  function TestSliceOfStruct (line 589) | func TestSliceOfStruct(t *testing.T) {
  function TestInvalidType (line 618) | func TestInvalidType(t *testing.T) {
  function TestMetadata (line 641) | func TestMetadata(t *testing.T) {
  function TestMetadata_Embedded (line 682) | func TestMetadata_Embedded(t *testing.T) {
  function TestNonPtrValue (line 720) | func TestNonPtrValue(t *testing.T) {
  function TestTagged (line 733) | func TestTagged(t *testing.T) {
  function testSliceInput (line 756) | func testSliceInput(t *testing.T, input map[string]interface{}, expected...
  function TestDecodePath (line 784) | func TestDecodePath(t *testing.T) {
  function TestDecodeSlicePath (line 888) | func TestDecodeSlicePath(t *testing.T) {
  function TestDecodeWithEmbeddedSlice (line 933) | func TestDecodeWithEmbeddedSlice(t *testing.T) {
  function TestDecodeWithAbstractField (line 1015) | func TestDecodeWithAbstractField(t *testing.T) {
  function TestDecodePointerToPointer (line 1039) | func TestDecodePointerToPointer(t *testing.T) {
Condensed preview — 8 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (76K chars).
[
  {
    "path": "LICENSE",
    "chars": 1102,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Mitchell Hashimoto, William Kennedy\n\nPermission is hereby granted, free of cha"
  },
  {
    "path": "README.md",
    "chars": 5376,
    "preview": "# mapstructure\n\nmapstructure is a Go library for decoding generic map values to structures\nand vice versa, while providi"
  },
  {
    "path": "error.go",
    "chars": 650,
    "preview": "package mapstructure\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Error implements the error interface and can represents multiple\n"
  },
  {
    "path": "mapstructure.go",
    "chars": 24112,
    "preview": "// The mapstructure package exposes functionality to convert an\n// abitrary map[string]interface{} into a native Go stru"
  },
  {
    "path": "mapstructure_benchmark_test.go",
    "chars": 4544,
    "preview": "package mapstructure\n\nimport (\n\t\"testing\"\n)\n\nfunc Benchmark_Decode(b *testing.B) {\n\ttype Person struct {\n\t\tName   string"
  },
  {
    "path": "mapstructure_bugs_test.go",
    "chars": 856,
    "preview": "package mapstructure\n\nimport \"testing\"\n\n// GH-1\nfunc TestDecode_NilValue(t *testing.T) {\n\tinput := map[string]interface{"
  },
  {
    "path": "mapstructure_examples_test.go",
    "chars": 8350,
    "preview": "package mapstructure\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\nfunc ExampleDecode() {\n\ttype Person struct {\n\t\tName   string\n\t"
  },
  {
    "path": "mapstructure_test.go",
    "chars": 22503,
    "preview": "package mapstructure\n\nimport (\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n)\n\ntype Basic struct {\n\tVstring string\n\tVi"
  }
]

About this extraction

This page contains the full source code of the goinggo/mapstructure GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 8 files (65.9 KB), approximately 19.5k tokens, and a symbol index with 86 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!