diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index 6c09071e0..786233f7a 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -366,15 +366,29 @@ func bindVarToStructAttr(structReflectValue reflect.Value, attrName string, valu if empty.IsNil(value) { structFieldValue.Set(reflect.Zero(structFieldValue.Type())) } else { + // Special handling for certain types: + // - Overwrite the default type converting logic of stdlib for time.Time/*time.Time. + var structFieldTypeName = structFieldValue.Type().String() + switch structFieldTypeName { + case "time.Time", "*time.Time": + doConvertWithReflectValueSet(structFieldValue, doConvertInput{ + FromValue: value, + ToTypeName: structFieldTypeName, + ReferValue: structFieldValue, + }) + return + } + // Common interface check. var ok bool if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { return err } + // Default converting. doConvertWithReflectValueSet(structFieldValue, doConvertInput{ FromValue: value, - ToTypeName: structFieldValue.Type().String(), + ToTypeName: structFieldTypeName, ReferValue: structFieldValue, }) } diff --git a/util/gconv/gconv_z_unit_issue_test.go b/util/gconv/gconv_z_unit_issue_test.go index f809050b4..6caddd70f 100644 --- a/util/gconv/gconv_z_unit_issue_test.go +++ b/util/gconv/gconv_z_unit_issue_test.go @@ -8,6 +8,7 @@ package gconv_test import ( "testing" + "time" "github.com/gogf/gf/v2/container/gtype" "github.com/gogf/gf/v2/encoding/gjson" @@ -275,3 +276,19 @@ func Test_Issue2395(t *testing.T) { t.Assert(gconv.Interfaces(obj), []interface{}{obj}) }) } + +// https://github.com/gogf/gf/issues/2371 +func Test_Issue2371(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + s = struct { + Time time.Time `json:"time"` + }{} + jsonMap = map[string]interface{}{"time": "2022-12-15 16:11:34"} + ) + + err := gconv.Struct(jsonMap, &s) + t.AssertNil(err) + t.Assert(s.Time.UTC(), `2022-12-15 08:11:34 +0000 UTC`) + }) +}