diff --git a/encoding/gjson/gjson.go b/encoding/gjson/gjson.go index a5cf93876..344fc4235 100644 --- a/encoding/gjson/gjson.go +++ b/encoding/gjson/gjson.go @@ -35,8 +35,8 @@ type Json struct { // Options for Json object creating. type Options struct { - Safe bool // Mark this object is for in concurrent-safe usage. - Tags string // Custom priority tags for decoding. + Safe bool // Mark this object is for in concurrent-safe usage. This is especially for Json object creating. + Tags string // Custom priority tags for decoding. Eg: "json,yaml,MyTag". This is especially for struct parsing into Json object. StrNumber bool // StrNumber causes the Decoder to unmarshal a number into an interface{} as a string instead of as a float64. } diff --git a/encoding/gjson/gjson_stdlib_json_util.go b/encoding/gjson/gjson_stdlib_json_util.go index 35a4ff430..24c404a82 100644 --- a/encoding/gjson/gjson_stdlib_json_util.go +++ b/encoding/gjson/gjson_stdlib_json_util.go @@ -48,9 +48,9 @@ func MustEncodeString(value interface{}) string { // Decode decodes json format `data` to golang variable. // The parameter `data` can be either bytes or string type. -func Decode(data interface{}) (interface{}, error) { +func Decode(data interface{}, options ...Options) (interface{}, error) { var value interface{} - if err := DecodeTo(gconv.Bytes(data), &value); err != nil { + if err := DecodeTo(gconv.Bytes(data), &value, options...); err != nil { return nil, err } else { return value, nil @@ -60,21 +60,27 @@ func Decode(data interface{}) (interface{}, error) { // DecodeTo decodes json format `data` to specified golang variable `v`. // The parameter `data` can be either bytes or string type. // The parameter `v` should be a pointer type. -func DecodeTo(data interface{}, v interface{}) error { +func DecodeTo(data interface{}, v interface{}, options ...Options) error { decoder := json.NewDecoder(bytes.NewReader(gconv.Bytes(data))) - // Do not use number, it converts float64 to json.Number type, - // which actually a string type. It causes converting issue for other data formats, - // for example: yaml. - // decoder.UseNumber() + if len(options) > 0 { + // The StrNumber option is for certain situations, not for all. + // For example, it causes converting issue for other data formats, for example: yaml. + if options[0].StrNumber { + decoder.UseNumber() + } + } return decoder.Decode(v) } // DecodeToJson codes json format `data` to a Json object. // The parameter `data` can be either bytes or string type. -func DecodeToJson(data interface{}, safe ...bool) (*Json, error) { - if v, err := Decode(gconv.Bytes(data)); err != nil { +func DecodeToJson(data interface{}, options ...Options) (*Json, error) { + if v, err := Decode(gconv.Bytes(data), options...); err != nil { return nil, err } else { - return New(v, safe...), nil + if len(options) > 0 { + return New(v, options[0].Safe), nil + } + return New(v), nil } } diff --git a/encoding/gjson/gjson_z_unit_test.go b/encoding/gjson/gjson_z_unit_test.go index a77eacd29..7317ef538 100644 --- a/encoding/gjson/gjson_z_unit_test.go +++ b/encoding/gjson/gjson_z_unit_test.go @@ -7,6 +7,7 @@ package gjson_test import ( + "fmt" "testing" "github.com/gogf/gf/v2/container/gmap" @@ -515,3 +516,23 @@ func TestJson_Set_With_Struct(t *testing.T) { t.Assert(v.Get("user1.id"), 111) }) } + +func TestJson_Options(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type S struct { + Id int64 + } + s := S{ + Id: 53687091200, + } + m := make(map[string]interface{}) + t.AssertNil(gjson.DecodeTo(gjson.MustEncode(s), &m, gjson.Options{ + StrNumber: false, + })) + t.Assert(fmt.Sprintf(`%v`, m["Id"]), `5.36870912e+10`) + t.AssertNil(gjson.DecodeTo(gjson.MustEncode(s), &m, gjson.Options{ + StrNumber: true, + })) + t.Assert(fmt.Sprintf(`%v`, m["Id"]), `53687091200`) + }) +}