From 2461ef9f29c6d72e316bc0f695d8901ce379cb00 Mon Sep 17 00:00:00 2001 From: John Guo Date: Thu, 17 Feb 2022 11:46:35 +0800 Subject: [PATCH] fix issue #1597 --- encoding/gbinary/gbinary_le.go | 2 +- internal/json/json.go | 5 +++++ util/gconv/gconv.go | 12 ++++++++++++ util/gconv/gconv_struct.go | 4 ++-- util/gconv/gconv_z_unit_struct_test.go | 24 ++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/encoding/gbinary/gbinary_le.go b/encoding/gbinary/gbinary_le.go index f3d197692..76186c46f 100644 --- a/encoding/gbinary/gbinary_le.go +++ b/encoding/gbinary/gbinary_le.go @@ -29,7 +29,6 @@ func LeEncode(values ...interface{}) []byte { if values[i] == nil { return buf.Bytes() } - switch value := values[i].(type) { case int: buf.Write(LeEncodeInt(value)) @@ -61,6 +60,7 @@ func LeEncode(values ...interface{}) []byte { buf.Write(LeEncodeFloat32(value)) case float64: buf.Write(LeEncodeFloat64(value)) + default: if err := binary.Write(buf, binary.LittleEndian, value); err != nil { intlog.Errorf(context.TODO(), `%+v`, err) diff --git a/internal/json/json.go b/internal/json/json.go index 7ad3da130..374aec688 100644 --- a/internal/json/json.go +++ b/internal/json/json.go @@ -15,6 +15,11 @@ import ( "github.com/gogf/gf/v2/errors/gerror" ) +// RawMessage is a raw encoded JSON value. +// It implements Marshaler and Unmarshaler and can +// be used to delay JSON decoding or precompute a JSON encoding. +type RawMessage = json.RawMessage + // Marshal adapts to json/encoding Marshal API. // // Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index c426ddf78..358ba5a06 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -10,6 +10,7 @@ package gconv import ( + "context" "fmt" "math" "reflect" @@ -18,6 +19,7 @@ import ( "time" "github.com/gogf/gf/v2/encoding/gbinary" + "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gtime" @@ -272,6 +274,9 @@ func doConvert(in doConvertInput) interface{} { case "[]map[string]interface{}": return Maps(in.FromValue) + case "json.RawMessage": + return Bytes(in.FromValue) + default: if in.ReferValue != nil { var ( @@ -316,6 +321,13 @@ func Bytes(any interface{}) []byte { } originValueAndKind := utils.OriginValueAndKind(any) switch originValueAndKind.OriginKind { + case reflect.Map: + bytes, err := json.Marshal(any) + if err != nil { + intlog.Errorf(context.TODO(), `%+v`, err) + } + return bytes + case reflect.Array, reflect.Slice: var ( ok = true diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index 381642a38..e73026549 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -421,7 +421,7 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma } // Common interface check. - if err, ok := bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { + if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { return err } @@ -500,7 +500,7 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma case reflect.Ptr: item := reflect.New(structFieldValue.Type().Elem()) - if err, ok := bindVarToReflectValueWithInterfaceCheck(item, value); ok { + if err, ok = bindVarToReflectValueWithInterfaceCheck(item, value); ok { structFieldValue.Set(item) return err } diff --git a/util/gconv/gconv_z_unit_struct_test.go b/util/gconv/gconv_z_unit_struct_test.go index e912936d2..c91a66468 100644 --- a/util/gconv/gconv_z_unit_struct_test.go +++ b/util/gconv/gconv_z_unit_struct_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/gogf/gf/v2/container/gvar" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/os/gtime" @@ -1277,3 +1278,26 @@ func Test_Struct_Issue1563(t *testing.T) { } }) } + +// https://github.com/gogf/gf/issues/1597 +func Test_Struct_Issue1597(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type S struct { + A int + B json.RawMessage + } + + jsonByte := []byte(`{ + "a":1, + "b":{ + "c": 3 + } + }`) + data, err := gjson.DecodeToJson(jsonByte) + t.AssertNil(err) + s := &S{} + err = data.Scan(s) + t.AssertNil(err) + t.Assert(s.B, `{"c":3}`) + }) +}