...

Source file src/github.com/clbanning/mxj/v2/rename.go

Documentation: github.com/clbanning/mxj/v2

     1  package mxj
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  )
     7  
     8  // RenameKey renames a key in a Map.
     9  // It works only for nested maps. 
    10  // It doesn't work for cases when the key is in a list.
    11  func (mv Map) RenameKey(path string, newName string) error {
    12  	var v bool
    13  	var err error
    14  	if v, err = mv.Exists(path); err == nil && !v {
    15  		return errors.New("RenameKey: path not found: " + path)
    16  	} else if err != nil {
    17  		return err
    18  	}
    19  	if v, err = mv.Exists(parentPath(path) + "." + newName); err == nil && v {
    20  		return errors.New("RenameKey: key already exists: " + newName)
    21  	} else if err != nil {
    22  		return err
    23  	}
    24  
    25  	m := map[string]interface{}(mv)
    26  	return renameKey(m, path, newName)
    27  }
    28  
    29  func renameKey(m interface{}, path string, newName string) error {
    30  	val, err := prevValueByPath(m, path)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	oldName := lastKey(path)
    36  	val[newName] = val[oldName]
    37  	delete(val, oldName)
    38  
    39  	return nil
    40  }
    41  
    42  // returns a value which contains a last key in the path
    43  // For example: prevValueByPath("a.b.c", {a{b{c: 3}}}) returns {c: 3}
    44  func prevValueByPath(m interface{}, path string) (map[string]interface{}, error) {
    45  	keys := strings.Split(path, ".")
    46  
    47  	switch mValue := m.(type) {
    48  	case map[string]interface{}:
    49  		for key, value := range mValue {
    50  			if key == keys[0] {
    51  				if len(keys) == 1 {
    52  					return mValue, nil
    53  				} else {
    54  					// keep looking for the full path to the key
    55  					return prevValueByPath(value, strings.Join(keys[1:], "."))
    56  				}
    57  			}
    58  		}
    59  	}
    60  	return nil, errors.New("prevValueByPath: didn't find path – " + path)
    61  }
    62  

View as plain text