add array struct and map supported
This commit is contained in:
parent
fbb08c6eb4
commit
9cfa81115f
|
@ -1,6 +1,7 @@
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -11,6 +12,10 @@ var (
|
||||||
allowTags = []string{"json", "yaml", "xml", "name"}
|
allowTags = []string{"json", "yaml", "xml", "name"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrValueAssociated = errors.New("value cannot be associated")
|
||||||
|
)
|
||||||
|
|
||||||
func findField(v reflect.Value, field string) reflect.Value {
|
func findField(v reflect.Value, field string) reflect.Value {
|
||||||
var (
|
var (
|
||||||
pos int
|
pos int
|
||||||
|
@ -64,7 +69,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
||||||
variable.SetInt(n)
|
variable.SetInt(n)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
err = fmt.Errorf("integer value can not assign %s", rv.Kind())
|
||||||
}
|
}
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
switch rv.Kind() {
|
switch rv.Kind() {
|
||||||
|
@ -79,7 +84,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
||||||
variable.SetUint(un)
|
variable.SetUint(un)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
err = fmt.Errorf("unsigned integer value can not assign %s", rv.Kind())
|
||||||
}
|
}
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
switch rv.Kind() {
|
switch rv.Kind() {
|
||||||
|
@ -94,7 +99,7 @@ func safeAssignment(variable reflect.Value, value interface{}) (err error) {
|
||||||
variable.SetFloat(fn)
|
variable.SetFloat(fn)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unsupported kind %s", rv.Kind())
|
err = fmt.Errorf("decimal value can not assign %s", rv.Kind())
|
||||||
}
|
}
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
switch rv.Kind() {
|
switch rv.Kind() {
|
||||||
|
@ -139,10 +144,30 @@ func Set(hacky interface{}, field string, value interface{}) (err error) {
|
||||||
}
|
}
|
||||||
switch fieldKind {
|
switch fieldKind {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
switch rv.Kind() {
|
if rv.Kind() != reflect.Map {
|
||||||
case reflect.Map:
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
keys := rv.MapKeys()
|
||||||
|
subVal := reflect.New(refField.Type())
|
||||||
|
for _, key := range keys {
|
||||||
|
pv := rv.MapIndex(key)
|
||||||
|
if key.Kind() == reflect.String {
|
||||||
|
if err = Set(subVal.Interface(), key.String(), pv.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refField.Set(subVal.Elem())
|
||||||
|
case reflect.Ptr:
|
||||||
|
elemType := refField.Type()
|
||||||
|
if elemType.Elem().Kind() != reflect.Struct {
|
||||||
|
return ErrValueAssociated
|
||||||
|
} else {
|
||||||
|
if rv.Kind() != reflect.Map {
|
||||||
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
keys := rv.MapKeys()
|
keys := rv.MapKeys()
|
||||||
subVal := reflect.New(refField.Type())
|
subVal := reflect.New(elemType.Elem())
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
pv := rv.MapIndex(key)
|
pv := rv.MapIndex(key)
|
||||||
if key.Kind() == reflect.String {
|
if key.Kind() == reflect.String {
|
||||||
|
@ -151,46 +176,102 @@ func Set(hacky interface{}, field string, value interface{}) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refField.Set(subVal.Elem())
|
refField.Set(subVal)
|
||||||
default:
|
|
||||||
err = fmt.Errorf("struct unsupported assign kind %s", rv.Kind())
|
|
||||||
}
|
}
|
||||||
case reflect.Ptr:
|
case reflect.Map:
|
||||||
elemType := refField.Type()
|
if rv.Kind() != reflect.Map {
|
||||||
if elemType.Elem().Kind() == reflect.Struct {
|
return ErrValueAssociated
|
||||||
switch rv.Kind() {
|
}
|
||||||
case reflect.Map:
|
targetValue := reflect.MakeMap(refField.Type())
|
||||||
keys := rv.MapKeys()
|
keys := rv.MapKeys()
|
||||||
subVal := reflect.New(elemType.Elem())
|
for _, key := range keys {
|
||||||
for _, key := range keys {
|
pv := rv.MapIndex(key)
|
||||||
pv := rv.MapIndex(key)
|
kVal := reflect.New(refField.Type().Key())
|
||||||
if key.Kind() == reflect.String {
|
eVal := reflect.New(refField.Type().Elem())
|
||||||
if err = Set(subVal.Interface(), key.String(), pv.Interface()); err != nil {
|
if err = safeAssignment(kVal.Elem(), key.Interface()); err != nil {
|
||||||
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
if refField.Type().Elem().Kind() == reflect.Struct {
|
||||||
|
if pv.Elem().Kind() != reflect.Map {
|
||||||
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
subKeys := pv.Elem().MapKeys()
|
||||||
|
for _, subKey := range subKeys {
|
||||||
|
subVal := pv.Elem().MapIndex(subKey)
|
||||||
|
if subKey.Kind() == reflect.String {
|
||||||
|
if err = Set(eVal.Interface(), subKey.String(), subVal.Interface()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
refField.Set(subVal)
|
targetValue.SetMapIndex(kVal.Elem(), eVal.Elem())
|
||||||
default:
|
} else {
|
||||||
err = fmt.Errorf("struct unsupported assign kind %s", rv.Kind())
|
if err = safeAssignment(eVal.Elem(), pv.Interface()); err != nil {
|
||||||
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
targetValue.SetMapIndex(kVal.Elem(), eVal.Elem())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("ptr can't set kind %s", elemType.Elem().Kind())
|
|
||||||
}
|
}
|
||||||
|
refField.Set(targetValue)
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
|
n = 0
|
||||||
innerType := refField.Type().Elem()
|
innerType := refField.Type().Elem()
|
||||||
if rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice {
|
if rv.Kind() == reflect.Array || rv.Kind() == reflect.Slice {
|
||||||
sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
if innerType.Kind() == reflect.Struct {
|
||||||
n = 0
|
sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
||||||
for i := 0; i < rv.Len(); i++ {
|
for i := 0; i < rv.Len(); i++ {
|
||||||
srcVal := rv.Index(i)
|
srcVal := rv.Index(i)
|
||||||
dstVal := reflect.New(innerType).Elem()
|
if srcVal.Kind() != reflect.Map {
|
||||||
if err = safeAssignment(dstVal, srcVal); err == nil {
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
dstVal := reflect.New(innerType)
|
||||||
|
keys := srcVal.MapKeys()
|
||||||
|
for _, key := range keys {
|
||||||
|
kv := srcVal.MapIndex(key)
|
||||||
|
if key.Kind() == reflect.String {
|
||||||
|
if err = Set(dstVal.Interface(), key.String(), kv.Interface()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sliceVar.Index(n).Set(dstVal.Elem())
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
refField.Set(sliceVar.Slice(0, n))
|
||||||
|
} else if innerType.Kind() == reflect.Ptr {
|
||||||
|
sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
||||||
|
for i := 0; i < rv.Len(); i++ {
|
||||||
|
srcVal := rv.Index(i)
|
||||||
|
if srcVal.Kind() != reflect.Map {
|
||||||
|
return ErrValueAssociated
|
||||||
|
}
|
||||||
|
dstVal := reflect.New(innerType.Elem())
|
||||||
|
keys := srcVal.MapKeys()
|
||||||
|
for _, key := range keys {
|
||||||
|
kv := srcVal.MapIndex(key)
|
||||||
|
if key.Kind() == reflect.String {
|
||||||
|
if err = Set(dstVal.Interface(), key.String(), kv.Interface()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
sliceVar.Index(n).Set(dstVal)
|
sliceVar.Index(n).Set(dstVal)
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
|
refField.Set(sliceVar.Slice(0, n))
|
||||||
|
} else {
|
||||||
|
sliceVar := reflect.MakeSlice(refField.Type(), rv.Len(), rv.Len())
|
||||||
|
for i := 0; i < rv.Len(); i++ {
|
||||||
|
srcVal := rv.Index(i)
|
||||||
|
dstVal := reflect.New(innerType).Elem()
|
||||||
|
if err = safeAssignment(dstVal, srcVal.Interface()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sliceVar.Index(n).Set(dstVal)
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
refField.Set(sliceVar.Slice(0, n))
|
||||||
}
|
}
|
||||||
refField.Set(sliceVar.Slice(0, n))
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
err = safeAssignment(refField, value)
|
err = safeAssignment(refField, value)
|
||||||
|
|
|
@ -6,17 +6,50 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Fakeb struct {
|
type Fakeb struct {
|
||||||
In int `json:"in"`
|
In int `json:"in"`
|
||||||
|
BS map[string]string `json:"bs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Ab struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
type fake struct {
|
type fake struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Age int `json:"age"`
|
Age int `json:"age"`
|
||||||
Usage *Fakeb `json:"usage"`
|
Usage []Fakeb `json:"usage"`
|
||||||
|
XX Fakeb `json:"xx"`
|
||||||
|
AX *Fakeb `json:"ax"`
|
||||||
|
SS []string `json:"ss"`
|
||||||
|
DS []int `json:"ds"`
|
||||||
|
Ms map[string]int `json:"ms"`
|
||||||
|
AB map[string]Ab `json:"ab"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetter(t *testing.T) {
|
func TestSetter(t *testing.T) {
|
||||||
dst := &fake{}
|
dst := &fake{}
|
||||||
ms := map[string]any{"name": "aa", "age": "5", "usage": map[string]any{"in": 15}}
|
ms := map[string]any{
|
||||||
|
"name": "aa",
|
||||||
|
"age": "5",
|
||||||
|
"usage": []map[string]any{
|
||||||
|
{
|
||||||
|
"in": 15,
|
||||||
|
"bs": map[string]any{
|
||||||
|
"aa": "vv",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"xx": map[string]any{"in": 45},
|
||||||
|
"ax": map[string]any{"in": 55},
|
||||||
|
"ss": []string{"11", "ss"},
|
||||||
|
"ds": []int{55, 55, 34},
|
||||||
|
"ms": map[string]any{"aa": "23"},
|
||||||
|
"ab": map[string]any{
|
||||||
|
"xx": map[string]any{
|
||||||
|
"name": "xxx",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
err := Setter(dst, ms)
|
err := Setter(dst, ms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -25,7 +58,6 @@ func TestSetter(t *testing.T) {
|
||||||
if dst.Age != 5 {
|
if dst.Age != 5 {
|
||||||
t.Errorf("setter failed")
|
t.Errorf("setter failed")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(dst.Usage.In)
|
|
||||||
fmt.Printf("%+v", dst)
|
fmt.Printf("%+v", dst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue