improve package gconv

This commit is contained in:
John Guo
2021-01-17 20:56:38 +08:00
parent 91e29e23a4
commit 5c9cee7fb9
4 changed files with 46 additions and 25 deletions

View File

@ -112,11 +112,11 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
if err != nil {
return err
}
if err := j.GetStructs(".", pointer); err != nil {
if err = j.GetStructs(".", pointer); err != nil {
return err
}
for i := 0; i < reflectVal2.Len(); i++ {
if err := gvalid.CheckStruct(reflectVal2.Index(i), nil); err != nil {
if err = gvalid.CheckStruct(reflectVal2.Index(i), nil); err != nil {
return err
}
}

View File

@ -443,3 +443,12 @@ func (t *Time) UnmarshalJSON(b []byte) error {
t.Time = newTime.Time
return nil
}
//// UnmarshalValue is an interface implement which sets any type of value for Time.
//func (t *Time) UnmarshalValue(value interface{}) error {
// vTime := New(value)
// if vTime != nil {
// *t = *vTime
// }
// return gerror.Newf(`invalid time value: %v`, value)
//}

View File

@ -119,11 +119,9 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
return nil
}
// UnmarshalValue.
// Assign value with interface UnmarshalValue.
// Note that only pointer can implement interface UnmarshalValue.
if v, ok := pointerReflectValue.Interface().(apiUnmarshalValue); ok {
return v.UnmarshalValue(params)
// Normal unmarshalling interfaces checks.
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerReflectValue, params); ok {
return err
}
// It automatically creates struct object if necessary.
@ -133,8 +131,13 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
e := reflect.New(pointerElemReflectValue.Type().Elem()).Elem()
pointerElemReflectValue.Set(e.Addr())
}
if v, ok := pointerElemReflectValue.Interface().(apiUnmarshalValue); ok {
return v.UnmarshalValue(params)
fmt.Println(pointerElemReflectValue.Type())
//if v, ok := pointerElemReflectValue.Interface().(apiUnmarshalValue); ok {
// return v.UnmarshalValue(params)
//}
// Note that it's `pointerElemReflectValue` here not `pointerReflectValue`.
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerElemReflectValue, params); ok {
return err
}
// Retrieve its element, may be struct at last.
pointerElemReflectValue = pointerElemReflectValue.Elem()
@ -286,25 +289,29 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}, map
}
// bindVarToReflectValueWithInterfaceCheck does binding using common interfaces checks.
func bindVarToReflectValueWithInterfaceCheck(structFieldValue reflect.Value, value interface{}) (err error, ok bool) {
if structFieldValue.CanAddr() {
pointer := structFieldValue.Addr().Interface()
if v, ok := pointer.(apiUnmarshalValue); ok {
return v.UnmarshalValue(value), ok
func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value interface{}) (err error, ok bool) {
var pointer interface{}
if reflectValue.Kind() != reflect.Ptr && reflectValue.CanAddr() {
// Not a pointer, but can token address, that makes it can be unmarshalled.
pointer = reflectValue.Addr().Interface()
} else {
pointer = reflectValue.Interface()
}
if v, ok := pointer.(apiUnmarshalValue); ok {
return v.UnmarshalValue(value), ok
}
if v, ok := pointer.(apiUnmarshalText); ok {
if s, ok := value.(string); ok {
return v.UnmarshalText([]byte(s)), ok
}
if v, ok := pointer.(apiUnmarshalText); ok {
if s, ok := value.(string); ok {
return v.UnmarshalText([]byte(s)), ok
}
if b, ok := value.([]byte); ok {
return v.UnmarshalText(b), ok
}
}
if v, ok := pointer.(apiSet); ok {
v.Set(value)
return nil, ok
if b, ok := value.([]byte); ok {
return v.UnmarshalText(b), ok
}
}
if v, ok := pointer.(apiSet); ok {
v.Set(value)
return nil, ok
}
return nil, false
}

View File

@ -48,6 +48,11 @@ func Test_Struct_UnmarshalValue1(t *testing.T) {
err := gconv.Struct(g.Map{"ServiceDate": nil}, st)
t.AssertNE(err, nil)
})
gtest.C(t, func(t *gtest.T) {
st := &MyTimeSt{}
err := gconv.Struct(g.Map{"ServiceDate": "error"}, st)
t.AssertNE(err, nil)
})
}
type Pkg struct {