util/reflect: ZeroFieldByPath and SetFieldByPath
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
bcaea675a7
commit
45f30c0be3
@ -72,9 +72,10 @@ func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, e
|
|||||||
// ZeroFieldByPath clean struct field by its path
|
// ZeroFieldByPath clean struct field by its path
|
||||||
func ZeroFieldByPath(src interface{}, path string) error {
|
func ZeroFieldByPath(src interface{}, path string) error {
|
||||||
var err error
|
var err error
|
||||||
var val reflect.Value
|
val := reflect.ValueOf(src)
|
||||||
|
|
||||||
for _, p := range strings.Split(path, ".") {
|
for _, p := range strings.Split(path, ".") {
|
||||||
val, err = structValueByName(reflect.ValueOf(src), p)
|
val, err = structValueByName(reflect.ValueOf(val), p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -93,6 +94,27 @@ func ZeroFieldByPath(src interface{}, path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFieldByPath set struct field by its path
|
||||||
|
func SetFieldByPath(src interface{}, dst interface{}, path string) error {
|
||||||
|
var err error
|
||||||
|
val := reflect.ValueOf(src)
|
||||||
|
|
||||||
|
for _, p := range strings.Split(path, ".") {
|
||||||
|
val, err = structValueByName(val, p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !val.CanSet() {
|
||||||
|
return ErrInvalidStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
val.Set(reflect.ValueOf(dst))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// structValueByName get struct field by its name
|
// structValueByName get struct field by its name
|
||||||
func structValueByName(sv reflect.Value, tkey string) (reflect.Value, error) {
|
func structValueByName(sv reflect.Value, tkey string) (reflect.Value, error) {
|
||||||
if sv.Kind() == reflect.Ptr {
|
if sv.Kind() == reflect.Ptr {
|
||||||
|
@ -8,6 +8,40 @@ import (
|
|||||||
rutil "go.unistack.org/micro/v3/util/reflect"
|
rutil "go.unistack.org/micro/v3/util/reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSetFieldByPath(t *testing.T) {
|
||||||
|
type NestedStr struct {
|
||||||
|
BBB string
|
||||||
|
CCC int
|
||||||
|
}
|
||||||
|
type Str1 struct {
|
||||||
|
Name []string `json:"name" codec:"flatten"`
|
||||||
|
XXX string `json:"xxx"`
|
||||||
|
Nested NestedStr
|
||||||
|
}
|
||||||
|
type Str2 struct {
|
||||||
|
XXX string `json:"xxx"`
|
||||||
|
Nested *NestedStr
|
||||||
|
Name []string `json:"name" codec:"flatten"`
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
val1 := &Str1{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
|
||||||
|
val2 := &Str2{Name: []string{"first", "second"}, XXX: "ttt", Nested: &NestedStr{BBB: "ddd", CCC: 9}}
|
||||||
|
err = rutil.SetFieldByPath(val1, "xxx", "Nested.BBB")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if val1.Nested.BBB != "xxx" {
|
||||||
|
t.Fatalf("SetFieldByPath not works: %#+v", val1)
|
||||||
|
}
|
||||||
|
err = rutil.SetFieldByPath(val2, "xxx", "Nested.BBB")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if val2.Nested.BBB != "xxx" {
|
||||||
|
t.Fatalf("SetFieldByPath not works: %#+v", val1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestZeroFieldByPath(t *testing.T) {
|
func TestZeroFieldByPath(t *testing.T) {
|
||||||
type NestedStr struct {
|
type NestedStr struct {
|
||||||
BBB string
|
BBB string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user