util/reflect: add ability to merge maps
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
faf2454f0a
commit
6641463eed
@ -44,6 +44,37 @@ func SliceAppend(b bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
var maxDepth = 32
|
||||
|
||||
func mergeMap(dst, src map[string]interface{}, depth int) map[string]interface{} {
|
||||
if depth > maxDepth {
|
||||
return dst
|
||||
}
|
||||
for key, srcVal := range src {
|
||||
if dstVal, ok := dst[key]; ok {
|
||||
srcMap, srcMapOk := mapify(srcVal)
|
||||
dstMap, dstMapOk := mapify(dstVal)
|
||||
if srcMapOk && dstMapOk {
|
||||
srcVal = mergeMap(dstMap, srcMap, depth+1)
|
||||
}
|
||||
}
|
||||
dst[key] = srcVal
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func mapify(i interface{}) (map[string]interface{}, bool) {
|
||||
value := reflect.ValueOf(i)
|
||||
if value.Kind() == reflect.Map {
|
||||
m := map[string]interface{}{}
|
||||
for _, k := range value.MapKeys() {
|
||||
m[k.String()] = value.MapIndex(k).Interface()
|
||||
}
|
||||
return m, true
|
||||
}
|
||||
return map[string]interface{}{}, false
|
||||
}
|
||||
|
||||
// Merge merges map[string]interface{} to destination struct
|
||||
func Merge(dst interface{}, mp map[string]interface{}, opts ...Option) error {
|
||||
options := Options{}
|
||||
@ -59,6 +90,11 @@ func Merge(dst interface{}, mp map[string]interface{}, opts ...Option) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if mapper, ok := dst.(map[string]interface{}); ok {
|
||||
dst = mergeMap(mapper, mp, 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
var sval reflect.Value
|
||||
var fname string
|
||||
|
@ -4,6 +4,27 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMergeMap(t *testing.T) {
|
||||
src := map[string]interface{}{
|
||||
"skey1": "sval1",
|
||||
"skey2": map[string]interface{}{
|
||||
"skey3": "sval3",
|
||||
},
|
||||
}
|
||||
dst := map[string]interface{}{
|
||||
"skey1": "dval1",
|
||||
"skey2": map[string]interface{}{
|
||||
"skey3": "dval3",
|
||||
},
|
||||
}
|
||||
|
||||
if err := Merge(src, dst); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("%#+v", src)
|
||||
}
|
||||
|
||||
func TestFieldName(t *testing.T) {
|
||||
src := "SomeVar"
|
||||
chk := "some_var"
|
||||
|
Loading…
Reference in New Issue
Block a user