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
|
// Merge merges map[string]interface{} to destination struct
|
||||||
func Merge(dst interface{}, mp map[string]interface{}, opts ...Option) error {
|
func Merge(dst interface{}, mp map[string]interface{}, opts ...Option) error {
|
||||||
options := Options{}
|
options := Options{}
|
||||||
@ -59,6 +90,11 @@ func Merge(dst interface{}, mp map[string]interface{}, opts ...Option) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mapper, ok := dst.(map[string]interface{}); ok {
|
||||||
|
dst = mergeMap(mapper, mp, 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var sval reflect.Value
|
var sval reflect.Value
|
||||||
var fname string
|
var fname string
|
||||||
|
@ -4,6 +4,27 @@ import (
|
|||||||
"testing"
|
"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) {
|
func TestFieldName(t *testing.T) {
|
||||||
src := "SomeVar"
|
src := "SomeVar"
|
||||||
chk := "some_var"
|
chk := "some_var"
|
||||||
|
Loading…
Reference in New Issue
Block a user