func (mv Map) ValueOrEmptyForPathString(path string) string {
	str, _ := mv.ValueForPathString(path)
	return str
}
ValueOrEmptyForPathString returns the first found value for the path as a string.
If the path is not found then it returns an empty string.
package mxj
import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)
const (
	minArraySize = 32
)
var defaultArraySize int = minArraySize
func SetArraySize(size int) int {
	if size > minArraySize {
		defaultArraySize = size
	} else {
		defaultArraySize = minArraySize
	}
	return defaultArraySize
}
func (mv Map) ValuesForKey(key string, subkeys ...string) ([]interface{}, error) {
	m := map[string]interface{}(mv)
	var subKeyMap map[string]interface{}
	if len(subkeys) > 0 {
		var err error
		subKeyMap, err = getSubKeyMap(subkeys...)
		if err != nil {
			return nil, err
		}
	}
	ret := make([]interface{}, 0, defaultArraySize)
	var cnt int
	hasKey(m, key, &ret, &cnt, subKeyMap)
	return ret[:cnt], nil
}
var KeyNotExistError = errors.New("Key does not exist")
func (mv Map) ValueForKey(key string, subkeys ...string) (interface{}, error) {
	vals, err := mv.ValuesForKey(key, subkeys...)
	if err != nil {
		return nil, err
	}
	if len(vals) == 0 {
		return nil, KeyNotExistError
	}
	return vals[0], nil
}
func hasKey(iv interface{}, key string, ret *[]interface{}, cnt *int, subkeys map[string]interface{}) {
	switch iv.(type) {
	case map[string]interface{}:
		vv := iv.(map[string]interface{})
		if v, ok := vv[key]; ok {
			switch v.(type) {
			case map[string]interface{}:
				if hasSubKeys(v, subkeys) {
					*ret = append(*ret, v)
					*cnt++
				}
			case []interface{}:
				for _, av := range v.([]interface{}) {
					if hasSubKeys(av, subkeys) {
						*ret = append(*ret, av)
						*cnt++
					}
				}
			default:
				if len(subkeys) == 0 {
					*ret = append(*ret, v)
					*cnt++
				}
			}
		}
		if key == "*" {
			for _, v := range vv {
				switch v.(type) {
				case map[string]interface{}:
					if hasSubKeys(v, subkeys) {
						*ret = append(*ret, v)
						*cnt++
					}
				case []interface{}:
					for _, av := range v.([]interface{}) {
						if hasSubKeys(av, subkeys) {
							*ret = append(*ret, av)
							*cnt++
						}
					}
				default:
					if len(subkeys) == 0 {
						*ret = append(*ret, v)
						*cnt++
					}
				}
			}
		}
		for _, v := range vv {
			hasKey(v, key, ret, cnt, subkeys)
		}
	case []interface{}:
		for _, v := range iv.([]interface{}) {
			hasKey(v, key, ret, cnt, subkeys)
		}
	}
}
func (mv Map) ValuesForPath(path string, subkeys ...string) ([]interface{}, error) {
	if strings.Index(path, "[") < 0 {
		return mv.oldValuesForPath(path, subkeys...)
	}
	var subKeyMap map[string]interface{}
	if len(subkeys) > 0 {
		var err error
		subKeyMap, err = getSubKeyMap(subkeys...)
		if err != nil {
			return nil, err
		}
	}
	keys, kerr := parsePath(path)
	if kerr != nil {
		return nil, kerr
	}
	vals, verr := valuesForArray(keys, mv)
	if verr != nil {
		return nil, verr  
	}
	retvals := make([]interface{}, 0)
	for _, v := range vals {
		if hasSubKeys(v, subKeyMap) {
			retvals = append(retvals, v)
		}
	}
	return retvals, nil
}
func valuesForArray(keys []*key, m Map) ([]interface{}, error) {
	var tmppath string
	var haveFirst bool
	var vals []interface{}
	var verr error
	lastkey := len(keys) - 1
	for i := 0; i <= lastkey; i++ {
		if !haveFirst {
			tmppath = keys[i].name
			haveFirst = true
		} else {
			tmppath += "." + keys[i].name
		}
		if !keys[i].isArray && i < lastkey && keys[i+1].isArray {
			vv, vverr := m.oldValuesForPath(tmppath)
			if vverr != nil {
				return nil, vverr
			}
			for _, v := range vv {
				am, ok := v.(map[string]interface{})
				if !ok {
					continue
				}
				nvals, nvalserr := valuesForArray(keys[i+1:], Map(am))
				if nvalserr != nil {
					return nil, nvalserr
				}
				vals = append(vals, nvals...)
			}
			break  
		}
		if keys[i].isArray || i == lastkey {
			vals, verr = m.oldValuesForPath(tmppath)
		} else {
			continue
		}
		if verr != nil {
			return nil, verr
		}
		if i == lastkey && !keys[i].isArray {
			break
		}
		if len(vals) <= keys[i].position {
			vals = nil
			break
		}
		if i == lastkey {
			vals = vals[keys[i].position:(keys[i].position + 1)]
			break
		}
		am := vals[keys[i].position:(keys[i].position + 1)]
		amm, ok := am[0].(map[string]interface{})
		if !ok {
			vals = nil
			break
		}
		m = Map(amm)
		haveFirst = false
	}
	return vals, nil
}
type key struct {
	name     string
	isArray  bool
	position int
}
func parsePath(s string) ([]*key, error) {
	keys := strings.Split(s, ".")
	ret := make([]*key, 0)
	for i := 0; i < len(keys); i++ {
		if keys[i] == "" {
			continue
		}
		newkey := new(key)
		if strings.Index(keys[i], "[") < 0 {
			newkey.name = keys[i]
			ret = append(ret, newkey)
			continue
		}
		p := strings.Split(keys[i], "[")
		newkey.name = p[0]
		p = strings.Split(p[1], "]")
		if p[0] == "" {  
			return nil, fmt.Errorf("no right bracket on key index: %s", keys[i])
		}
		pos, nerr := strconv.ParseInt(p[0], 10, 32)
		if nerr != nil {
			return nil, fmt.Errorf("cannot convert index to int value: %s", p[0])
		}
		newkey.position = int(pos)
		newkey.isArray = true
		ret = append(ret, newkey)
	}
	return ret, nil
}
func (mv Map) oldValuesForPath(path string, subkeys ...string) ([]interface{}, error) {
	m := map[string]interface{}(mv)
	var subKeyMap map[string]interface{}
	if len(subkeys) > 0 {
		var err error
		subKeyMap, err = getSubKeyMap(subkeys...)
		if err != nil {
			return nil, err
		}
	}
	keys := strings.Split(path, ".")
	if keys[len(keys)-1] == "" {
		keys = keys[:len(keys)-1]
	}
	ivals := make([]interface{}, 0, defaultArraySize)
	var cnt int
	valuesForKeyPath(&ivals, &cnt, m, keys, subKeyMap)
	return ivals[:cnt], nil
}
func valuesForKeyPath(ret *[]interface{}, cnt *int, m interface{}, keys []string, subkeys map[string]interface{}) {
	lenKeys := len(keys)
	if lenKeys == 0 {
		switch m.(type) {
		case map[string]interface{}:
			if subkeys != nil {
				if ok := hasSubKeys(m, subkeys); !ok {
					return
				}
			}
			*ret = append(*ret, m)
			*cnt++
		case []interface{}:
			for i, v := range m.([]interface{}) {
				if subkeys != nil {
					if ok := hasSubKeys(v, subkeys); !ok {
						continue  
					}
				}
				*ret = append(*ret, (m.([]interface{}))[i])
				*cnt++
			}
		default:
			if subkeys != nil {
				return  
			}
			*ret = append(*ret, m)
			*cnt++
		}
		return
	}
	key := keys[0]
	switch key {
	case "*":  
		switch m.(type) {
		case map[string]interface{}:
			for _, v := range m.(map[string]interface{}) {
				valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
			}
		case []interface{}:
			for _, v := range m.([]interface{}) {
				switch v.(type) {
				case map[string]interface{}:
					for _, vv := range v.(map[string]interface{}) {
						valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys)
					}
				default:
					valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
				}
			}
		}
	default:  
		switch m.(type) {
		case map[string]interface{}:
			if v, ok := m.(map[string]interface{})[key]; ok {
				valuesForKeyPath(ret, cnt, v, keys[1:], subkeys)
			}
		case []interface{}:  
			for _, v := range m.([]interface{}) {
				switch v.(type) {
				case map[string]interface{}:
					if vv, ok := v.(map[string]interface{})[key]; ok {
						valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys)
					}
				}
			}
		}
	}
}
func hasSubKeys(v interface{}, subkeys map[string]interface{}) bool {
	if len(subkeys) == 0 {
		return true
	}
	switch v.(type) {
	case map[string]interface{}:
		mv := v.(map[string]interface{})
		for skey, sval := range subkeys {
			isNotKey := false
			if skey[:1] == "!" {  
				skey = skey[1:]
				isNotKey = true
			}
			vv, ok := mv[skey]
			if !ok {  
				if isNotKey {  
					if kv, ok := sval.(string); ok && kv == "*" {
						continue
					}
				}
				return false
			}
			if kv, ok := sval.(string); ok && kv == "*" {
				if isNotKey {  
					return false
				}
				continue
			}
			switch sval.(type) {
			case string:
				if s, ok := vv.(string); ok && s == sval.(string) {
					if isNotKey {
						return false
					}
					continue
				}
			case bool:
				if b, ok := vv.(bool); ok && b == sval.(bool) {
					if isNotKey {
						return false
					}
					continue
				}
			case float64:
				if f, ok := vv.(float64); ok && f == sval.(float64) {
					if isNotKey {
						return false
					}
					continue
				}
			}
			if isNotKey {  
				continue
			}
			return false
		}
		return true
	}
	return false
}
func getSubKeyMap(kv ...string) (map[string]interface{}, error) {
	if len(kv) == 0 {
		return nil, nil
	}
	m := make(map[string]interface{}, 0)
	for _, v := range kv {
		vv := strings.Split(v, fieldSep)
		switch len(vv) {
		case 2:
			m[vv[0]] = interface{}(vv[1])
		case 3:
			switch vv[2] {
			case "string", "char", "text":
				m[vv[0]] = interface{}(vv[1])
			case "bool", "boolean":
				b, err := strconv.ParseBool(vv[1])
				if err != nil {
					return nil, fmt.Errorf("can't convert subkey value to bool: %s", vv[1])
				}
				m[vv[0]] = interface{}(b)
			case "float", "float64", "num", "number", "numeric":
				f, err := strconv.ParseFloat(vv[1], 64)
				if err != nil {
					return nil, fmt.Errorf("can't convert subkey value to float: %s", vv[1])
				}
				m[vv[0]] = interface{}(f)
			default:
				return nil, fmt.Errorf("unknown subkey conversion spec: %s", v)
			}
		default:
			return nil, fmt.Errorf("unknown subkey spec: %s", v)
		}
	}
	return m, nil
}
func (mv Map) PathsForKey(key string) []string {
	m := map[string]interface{}(mv)
	breadbasket := make(map[string]bool, 0)
	breadcrumbs := ""
	hasKeyPath(breadcrumbs, m, key, breadbasket)
	if len(breadbasket) == 0 {
		return nil
	}
	res := make([]string, len(breadbasket))
	var i int
	for k := range breadbasket {
		res[i] = k
		i++
	}
	return res
}
func (mv Map) PathForKeyShortest(key string) string {
	paths := mv.PathsForKey(key)
	lp := len(paths)
	if lp == 0 {
		return ""
	}
	if lp == 1 {
		return paths[0]
	}
	shortest := paths[0]
	shortestLen := len(strings.Split(shortest, "."))
	for i := 1; i < len(paths); i++ {
		vlen := len(strings.Split(paths[i], "."))
		if vlen < shortestLen {
			shortest = paths[i]
			shortestLen = vlen
		}
	}
	return shortest
}
func hasKeyPath(crumbs string, iv interface{}, key string, basket map[string]bool) {
	switch iv.(type) {
	case map[string]interface{}:
		vv := iv.(map[string]interface{})
		if _, ok := vv[key]; ok {
			var nbc string
			if crumbs == "" {
				nbc = key
			} else {
				nbc = crumbs + "." + key
			}
			basket[nbc] = true
		}
		for k, v := range vv {
			var nbc string
			if crumbs == "" {
				nbc = k
			} else {
				nbc = crumbs + "." + k
			}
			hasKeyPath(nbc, v, key, basket)
		}
	case []interface{}:
		for _, v := range iv.([]interface{}) {
			hasKeyPath(crumbs, v, key, basket)
		}
	}
}
var PathNotExistError = errors.New("Path does not exist")
func (mv Map) ValueForPath(path string) (interface{}, error) {
	vals, err := mv.ValuesForPath(path)
	if err != nil {
		return nil, err
	}
	if len(vals) == 0 {
		return nil, PathNotExistError
	}
	return vals[0], nil
}
func (mv Map) ValueForPathString(path string) (string, error) {
	vals, err := mv.ValuesForPath(path)
	if err != nil {
		return "", err
	}
	if len(vals) == 0 {
		return "", errors.New("ValueForPath: path not found")
	}
	val := vals[0]
	return fmt.Sprintf("%v", val), nil
}