diff --git a/runtime.go b/runtime.go index 9941278..1a55830 100644 --- a/runtime.go +++ b/runtime.go @@ -285,6 +285,38 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { panic(self.panicTypeError(fmt.Sprintf("unsupported type %v for numeric conversion", val.Type()))) } +func fieldIndexByName(t reflect.Type, name string) []int { + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + + if !validGoStructName(f.Name) { + continue + } + + if f.Anonymous { + if a := fieldIndexByName(f.Type, name); a != nil { + return append([]int{i}, a...) + } + } + + if a := strings.SplitN(f.Tag.Get("json"), ",", 2); a[0] != "" { + if a[0] == "-" { + continue + } + + if a[0] == name { + return []int{i} + } + } + + if f.Name == name { + return []int{i} + } + } + + return nil +} + var typeOfValue = reflect.TypeOf(Value{}) // convertCallParameter converts request val to type t if possible. @@ -467,41 +499,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu s := reflect.New(t) for _, k := range o.propertyOrder { - var f *reflect.StructField + idx := fieldIndexByName(t, k) - for i := 0; i < t.NumField(); i++ { - ff := t.Field(i) - - if j := ff.Tag.Get("json"); j != "" { - if j == "-" { - continue - } - - a := strings.Split(j, ",") - - if a[0] == k { - f = &ff - break - } - } - - if ff.Name == k { - f = &ff - break - } - - if strings.EqualFold(ff.Name, k) { - f = &ff - } - } - - if f == nil { + if idx == nil { panic(self.panicTypeError("can't convert object; field %q was supplied but does not exist on target %v", k, t)) } ss := s - for _, i := range f.Index { + for _, i := range idx { if ss.Kind() == reflect.Ptr { if ss.IsNil() { if !ss.CanSet() { @@ -572,7 +578,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu s = v.Class() } - panic(self.panicTypeError("can't convert from %q to %q", s, t.String())) + panic(self.panicTypeError("can't convert from %q to %q", s, t)) } func (self *_runtime) toValue(value interface{}) Value { diff --git a/type_go_struct.go b/type_go_struct.go index 608ac66..12fa727 100644 --- a/type_go_struct.go +++ b/type_go_struct.go @@ -36,6 +36,10 @@ func _newGoStructObject(value reflect.Value) *_goStructObject { } func (self _goStructObject) getValue(name string) reflect.Value { + if f, ok := self.field(name); ok { + return reflect.Indirect(self.value).FieldByIndex(f.Index) + } + if validGoStructName(name) { // Do not reveal hidden or unexported fields if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) { @@ -51,24 +55,26 @@ func (self _goStructObject) getValue(name string) reflect.Value { } func (self _goStructObject) field(name string) (reflect.StructField, bool) { - return reflect.Indirect(self.value).Type().FieldByName(name) + t := reflect.Indirect(self.value).Type() + + if idx := fieldIndexByName(t, name); len(idx) > 0 { + return t.FieldByIndex(idx), true + } + + return reflect.StructField{}, false } func (self _goStructObject) method(name string) (reflect.Method, bool) { return reflect.Indirect(self.value).Type().MethodByName(name) } -func (self _goStructObject) setValue(name string, value Value) bool { - field, exists := self.field(name) - if !exists { +func (self _goStructObject) setValue(rt *_runtime, name string, value Value) bool { + if _, exists := self.field(name); !exists { return false } + fieldValue := self.getValue(name) - reflectValue, err := value.toReflectValue(field.Type.Kind()) - if err != nil { - panic(err) - } - fieldValue.Set(reflectValue) + fieldValue.Set(rt.convertCallParameter(value, fieldValue.Type())) return true } @@ -128,7 +134,7 @@ func goStructCanPut(self *_object, name string) bool { func goStructPut(self *_object, name string, value Value, throw bool) { object := self.value.(*_goStructObject) - if object.setValue(name, value) { + if object.setValue(self.runtime, name, value) { return }