func updateValue(key string, value interface{}, m interface{}, keys0 string, subkeys map[string]interface{}, cnt *int) {
	switch m.(type) {
	case map[string]interface{}:  
		if keys0 == "*" {
			for k := range m.(map[string]interface{}) {
				updateValue(key, value, m, k, subkeys, cnt)
			}
			return
		}
		endVal, _ := m.(map[string]interface{})[keys0]
		if key == keys0 {
			switch endVal.(type) {
			case map[string]interface{}:
				if hasSubKeys(m, subkeys) {
					(m.(map[string]interface{}))[keys0] = value
					(*cnt)++
				}
			case []interface{}:
				if hasSubKeys(m, subkeys) {
					(m.(map[string]interface{}))[keys0] = value
					(*cnt)++
					break
				}
				nv := make([]interface{}, 0)
				var valmodified bool
				for _, v := range endVal.([]interface{}) {
					if hasSubKeys(v, subkeys) {
						nv = append(nv, value)
						valmodified = true
						(*cnt)++
						continue
					}
					nv = append(nv, v)
				}
				if valmodified {
					(m.(map[string]interface{}))[keys0] = interface{}(nv)
				}
			default:  
				if hasSubKeys(m, subkeys) {
					(m.(map[string]interface{}))[keys0] = value
					(*cnt)++
				}
			}
			return
		}
		switch endVal.(type) {
		case map[string]interface{}:
			if !hasSubKeys(endVal, subkeys) {
				return
			}
			if _, ok := (endVal.(map[string]interface{}))[key]; ok {
				(endVal.(map[string]interface{}))[key] = value
				(*cnt)++
			}
		case []interface{}:  
			for _, v := range endVal.([]interface{}) {
				vv, vok := v.(map[string]interface{})
				if !vok {
					continue
				}
				if _, ok := vv[key]; !ok {
					continue
				}
				if !hasSubKeys(vv, subkeys) {
					continue
				}
				vv[key] = value
				(*cnt)++
			}
		}
	case []interface{}:  
		for _, v := range m.([]interface{}) {
			mm, ok := v.(map[string]interface{})
			if !ok {
				continue
			}
			if _, ok := mm[key]; !ok {
				continue
			}
			if !hasSubKeys(mm, subkeys) {
				continue
			}
			mm[key] = value
			(*cnt)++
		}
	}
}
change value if key and subkeys are present
package mxj
import (
	"fmt"
	"strconv"
	"strings"
)
func (mv Map) UpdateValuesForPath(newVal interface{}, path string, subkeys ...string) (int, 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 0, err
		}
	}
	var key string
	var val interface{}
	switch newVal.(type) {
	case map[string]interface{}, Map:
		switch newVal.(type) {  
		case Map:
			newVal = newVal.(Map).Old()
		}
		if len(newVal.(map[string]interface{})) != 1 {
			return 0, fmt.Errorf("newVal map can only have len == 1 - %+v", newVal)
		}
		for key, val = range newVal.(map[string]interface{}) {
		}
	case string:  
		ss := strings.Split(newVal.(string), fieldSep)
		n := len(ss)
		if n < 2 || n > 3 {
			return 0, fmt.Errorf("unknown newVal spec - %+v", newVal)
		}
		key = ss[0]
		if n == 2 {
			val = interface{}(ss[1])
		} else if n == 3 {
			switch ss[2] {
			case "bool", "boolean":
				nv, err := strconv.ParseBool(ss[1])
				if err != nil {
					return 0, fmt.Errorf("can't convert newVal to bool - %+v", newVal)
				}
				val = interface{}(nv)
			case "num", "numeric", "float", "int":
				nv, err := strconv.ParseFloat(ss[1], 64)
				if err != nil {
					return 0, fmt.Errorf("can't convert newVal to float64 - %+v", newVal)
				}
				val = interface{}(nv)
			default:
				return 0, fmt.Errorf("unknown type for newVal value - %+v", newVal)
			}
		}
	default:
		return 0, fmt.Errorf("invalid newVal type - %+v", newVal)
	}
	keys := strings.Split(path, ".")
	var count int
	updateValuesForKeyPath(key, val, m, keys, subKeyMap, &count)
	return count, nil
}
func updateValuesForKeyPath(key string, value interface{}, m interface{}, keys []string, subkeys map[string]interface{}, cnt *int) {
	if len(keys) == 1 {
		updateValue(key, value, m, keys[0], subkeys, cnt)
		return
	}
	switch keys[0] {
	case "*":  
		switch m.(type) {
		case map[string]interface{}:
			for _, v := range m.(map[string]interface{}) {
				updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt)
			}
		case []interface{}:
			for _, v := range m.([]interface{}) {
				switch v.(type) {
				case map[string]interface{}:
					for _, vv := range v.(map[string]interface{}) {
						updateValuesForKeyPath(key, value, vv, keys[1:], subkeys, cnt)
					}
				default:
					updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt)
				}
			}
		}
	default:  
		switch m.(type) {
		case map[string]interface{}:
			if v, ok := m.(map[string]interface{})[keys[0]]; ok {
				updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt)
			}
		case []interface{}:  
			for _, v := range m.([]interface{}) {
				switch v.(type) {
				case map[string]interface{}:
					if vv, ok := v.(map[string]interface{})[keys[0]]; ok {
						updateValuesForKeyPath(key, value, vv, keys[1:], subkeys, cnt)
					}
				}
			}
		}
	}
}