add options for Decode/DecodeTo/DecodeToJson functions of package gjson

This commit is contained in:
John Guo
2022-01-13 12:09:04 +08:00
parent e5613e8690
commit 6ded700f92
3 changed files with 39 additions and 12 deletions

View File

@ -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.
}

View File

@ -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
}
}

View File

@ -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`)
})
}