improve package gjson/gvar

This commit is contained in:
jianchenma
2021-01-19 14:26:17 +08:00
parent 6d05512c2f
commit 68247acab1
15 changed files with 428 additions and 259 deletions

View File

@ -106,11 +106,6 @@ func (v *Var) Int() int {
return gconv.Int(v.Val())
}
// Ints converts and returns <v> as []int.
func (v *Var) Ints() []int {
return gconv.Ints(v.Val())
}
// Int8 converts and returns <v> as int8.
func (v *Var) Int8() int8 {
return gconv.Int8(v.Val())
@ -136,11 +131,6 @@ func (v *Var) Uint() uint {
return gconv.Uint(v.Val())
}
// Uints converts and returns <v> as []uint.
func (v *Var) Uints() []uint {
return gconv.Uints(v.Val())
}
// Uint8 converts and returns <v> as uint8.
func (v *Var) Uint8() uint8 {
return gconv.Uint8(v.Val())
@ -171,44 +161,6 @@ func (v *Var) Float64() float64 {
return gconv.Float64(v.Val())
}
// Floats converts and returns <v> as []float64.
func (v *Var) Floats() []float64 {
return gconv.Floats(v.Val())
}
// Strings converts and returns <v> as []string.
func (v *Var) Strings() []string {
return gconv.Strings(v.Val())
}
// Interfaces converts and returns <v> as []interfaces{}.
func (v *Var) Interfaces() []interface{} {
return gconv.Interfaces(v.Val())
}
// Slice is alias of Interfaces.
func (v *Var) Slice() []interface{} {
return v.Interfaces()
}
// Array is alias of Interfaces.
func (v *Var) Array() []interface{} {
return v.Interfaces()
}
// Vars converts and returns <v> as []Var.
func (v *Var) Vars() []*Var {
array := gconv.Interfaces(v.Val())
if len(array) == 0 {
return nil
}
vars := make([]*Var, len(array))
for k, v := range array {
vars[k] = New(v)
}
return vars
}
// Time converts and returns <v> as time.Time.
// The parameter <format> specifies the format of the time string using gtime,
// eg: Y-m-d H:i:s.

View File

@ -0,0 +1,77 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gvar
import "github.com/gogf/gf/util/gconv"
// Ints converts and returns <v> as []int.
func (v *Var) Ints() []int {
return gconv.Ints(v.Val())
}
// Int64s converts and returns <v> as []int64.
func (v *Var) Int64s() []int64 {
return gconv.Int64s(v.Val())
}
// Uints converts and returns <v> as []uint.
func (v *Var) Uints() []uint {
return gconv.Uints(v.Val())
}
// Uint64s converts and returns <v> as []uint64.
func (v *Var) Uint64s() []uint64 {
return gconv.Uint64s(v.Val())
}
// Floats is alias of Float64s.
func (v *Var) Floats() []float64 {
return gconv.Floats(v.Val())
}
// Float32s converts and returns <v> as []float32.
func (v *Var) Float32s() []float32 {
return gconv.Float32s(v.Val())
}
// Float64s converts and returns <v> as []float64.
func (v *Var) Float64s() []float64 {
return gconv.Float64s(v.Val())
}
// Strings converts and returns <v> as []string.
func (v *Var) Strings() []string {
return gconv.Strings(v.Val())
}
// Interfaces converts and returns <v> as []interfaces{}.
func (v *Var) Interfaces() []interface{} {
return gconv.Interfaces(v.Val())
}
// Slice is alias of Interfaces.
func (v *Var) Slice() []interface{} {
return v.Interfaces()
}
// Array is alias of Interfaces.
func (v *Var) Array() []interface{} {
return v.Interfaces()
}
// Vars converts and returns <v> as []Var.
func (v *Var) Vars() []*Var {
array := gconv.Interfaces(v.Val())
if len(array) == 0 {
return nil
}
vars := make([]*Var, len(array))
for k, v := range array {
vars[k] = New(v)
}
return vars
}

View File

@ -221,62 +221,6 @@ func Test_Float64(t *testing.T) {
})
}
func Test_Ints(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Ints()[0], arr[0])
})
}
func Test_Floats(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []float64{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Floats()[0], arr[0])
})
}
func Test_Strings(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []string{"hello", "world"}
objOne := gvar.New(arr, true)
t.Assert(objOne.Strings()[0], arr[0])
})
}
func Test_Interfaces(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Interfaces(), arr)
})
}
func Test_Slice(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Slice(), arr)
})
}
func Test_Array(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
t.Assert(objOne.Array(), arr)
})
}
func Test_Vars(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
t.Assert(len(objOne.Vars()), 5)
t.Assert(objOne.Vars()[0].Int(), 1)
t.Assert(objOne.Vars()[4].Int(), 5)
})
}
func Test_Time(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var timeUnix int64 = 1556242660

View File

@ -14,7 +14,7 @@ import (
"testing"
)
func Test_Json(t *testing.T) {
func TestVar_Json(t *testing.T) {
// Marshal
gtest.C(t, func(t *gtest.T) {
s := "i love gf"

View File

@ -13,7 +13,7 @@ import (
"testing"
)
func Test_ListItemValues_Map(t *testing.T) {
func TestVar_ListItemValues_Map(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
listMap := g.List{
g.Map{"id": 1, "score": 100},
@ -34,7 +34,7 @@ func Test_ListItemValues_Map(t *testing.T) {
})
}
func Test_ListItemValues_Struct(t *testing.T) {
func TestVar_ListItemValues_Struct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type T struct {
Id int
@ -78,7 +78,7 @@ func Test_ListItemValues_Struct(t *testing.T) {
})
}
func Test_ListItemValuesUnique(t *testing.T) {
func TestVar_ListItemValuesUnique(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
listMap := g.List{
g.Map{"id": 1, "score": 100},

View File

@ -13,7 +13,7 @@ import (
"testing"
)
func Test_Map(t *testing.T) {
func TestVar_Map(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := g.Map{
"k1": "v1",
@ -24,3 +24,58 @@ func Test_Map(t *testing.T) {
t.Assert(objOne.Map()["k2"], m["k2"])
})
}
func TestVar_MapToMap(t *testing.T) {
// map[int]int -> map[string]string
// empty original map.
gtest.C(t, func(t *gtest.T) {
m1 := g.MapIntInt{}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(len(m1), len(m2))
})
// map[int]int -> map[string]string
gtest.C(t, func(t *gtest.T) {
m1 := g.MapIntInt{
1: 100,
2: 200,
}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["1"], m1[1])
t.Assert(m2["2"], m1[2])
})
// map[string]interface{} -> map[string]string
gtest.C(t, func(t *gtest.T) {
m1 := g.Map{
"k1": "v1",
"k2": "v2",
}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
// map[string]string -> map[string]interface{}
gtest.C(t, func(t *gtest.T) {
m1 := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
m2 := g.Map{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
// map[string]interface{} -> map[interface{}]interface{}
gtest.C(t, func(t *gtest.T) {
m1 := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
m2 := g.MapAnyAny{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
}

View File

@ -1,69 +0,0 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gvar_test
import (
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/test/gtest"
"testing"
)
func Test_MapToMap(t *testing.T) {
// map[int]int -> map[string]string
// empty original map.
gtest.C(t, func(t *gtest.T) {
m1 := g.MapIntInt{}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(len(m1), len(m2))
})
// map[int]int -> map[string]string
gtest.C(t, func(t *gtest.T) {
m1 := g.MapIntInt{
1: 100,
2: 200,
}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["1"], m1[1])
t.Assert(m2["2"], m1[2])
})
// map[string]interface{} -> map[string]string
gtest.C(t, func(t *gtest.T) {
m1 := g.Map{
"k1": "v1",
"k2": "v2",
}
m2 := g.MapStrStr{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
// map[string]string -> map[string]interface{}
gtest.C(t, func(t *gtest.T) {
m1 := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
m2 := g.Map{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
// map[string]interface{} -> map[interface{}]interface{}
gtest.C(t, func(t *gtest.T) {
m1 := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
m2 := g.MapAnyAny{}
t.Assert(gvar.New(m1).MapToMap(&m2), nil)
t.Assert(m2["k1"], m1["k1"])
t.Assert(m2["k2"], m1["k2"])
})
}

View File

@ -0,0 +1,111 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gvar_test
import (
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/test/gtest"
"testing"
)
func TestVar_Ints(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Ints()[0], arr[0])
})
}
func TestVar_Uints(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Uints()[0], arr[0])
})
}
func TestVar_Int64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Int64s()[0], arr[0])
})
}
func TestVar_Uint64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Uint64s()[0], arr[0])
})
}
func TestVar_Floats(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []float64{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Floats()[0], arr[0])
})
}
func TestVar_Float32s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []float32{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.AssertEQ(objOne.Float32s(), arr)
})
}
func TestVar_Float64s(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []float64{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.AssertEQ(objOne.Float64s(), arr)
})
}
func TestVar_Strings(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []string{"hello", "world"}
objOne := gvar.New(arr, true)
t.Assert(objOne.Strings()[0], arr[0])
})
}
func TestVar_Interfaces(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Interfaces(), arr)
})
}
func TestVar_Slice(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
t.Assert(objOne.Slice(), arr)
})
}
func TestVar_Array(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
t.Assert(objOne.Array(), arr)
})
}
func TestVar_Vars(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
t.Assert(len(objOne.Vars()), 5)
t.Assert(objOne.Vars()[0].Int(), 1)
t.Assert(objOne.Vars()[4].Int(), 5)
})
}

View File

@ -14,7 +14,7 @@ import (
"testing"
)
func Test_Struct(t *testing.T) {
func TestVar_Struct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type StTest struct {
Test int
@ -42,7 +42,7 @@ func Test_Struct(t *testing.T) {
})
}
func Test_Var_Attribute_Struct(t *testing.T) {
func TestVar_Var_Attribute_Struct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Uid int

View File

@ -19,7 +19,7 @@ import (
const (
// Separator char for hierarchical data access.
gDEFAULT_SPLIT_CHAR = '.'
defaultSplitChar = '.'
)
// The customized JSON struct.
@ -30,6 +30,13 @@ type Json struct {
vc bool // Violence Check(false in default), which is used to access data when the hierarchical data key contains separator char.
}
// Option for Json object creating.
type Option struct {
Safe bool // Mark this object is for in concurrent-safe usage.
Tags string // Custom priority tags for decoding.
StrNumber bool // StrNumber causes the Decoder to unmarshal a number into an interface{} as a string instead of as a float64.
}
// setValue sets <value> to <j> by <pattern>.
// Note:
// 1. If value is nil and removed is true, means deleting this value;

View File

@ -24,6 +24,11 @@ func (j *Json) Value() interface{} {
return *(j.p)
}
// Var returns the json value as *gvar.Var.
func (j *Json) Var() *gvar.Var {
return gvar.New(j.Value())
}
// IsNil checks whether the value pointed by <j> is nil.
func (j *Json) IsNil() bool {
j.mu.RLock()

View File

@ -42,15 +42,27 @@ func New(data interface{}, safe ...bool) *Json {
// The parameter <safe> specifies whether using this Json object in concurrent-safe context, which
// is false in default.
func NewWithTag(data interface{}, tags string, safe ...bool) *Json {
j := (*Json)(nil)
option := Option{
Tags: tags,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return NewWithOption(data, option)
}
// NewWithOption creates a Json object with any variable type of <data>, but <data> should be a map
// or slice for data access reason, or it will make no sense.
func NewWithOption(data interface{}, option Option) *Json {
var j *Json
switch data.(type) {
case string, []byte:
if r, err := LoadContent(gconv.Bytes(data)); err == nil {
if r, err := loadContentWithOption(data, option); err == nil {
j = r
} else {
j = &Json{
p: &data,
c: byte(gDEFAULT_SPLIT_CHAR),
c: byte(defaultSplitChar),
vc: false,
}
}
@ -69,26 +81,26 @@ func NewWithTag(data interface{}, tags string, safe ...bool) *Json {
i = gconv.Interfaces(data)
j = &Json{
p: &i,
c: byte(gDEFAULT_SPLIT_CHAR),
c: byte(defaultSplitChar),
vc: false,
}
case reflect.Map, reflect.Struct:
i := interface{}(nil)
i = gconv.MapDeep(data, tags)
i = gconv.MapDeep(data, option.Tags)
j = &Json{
p: &i,
c: byte(gDEFAULT_SPLIT_CHAR),
c: byte(defaultSplitChar),
vc: false,
}
default:
j = &Json{
p: &data,
c: byte(gDEFAULT_SPLIT_CHAR),
c: byte(defaultSplitChar),
vc: false,
}
}
}
j.mu = rwmutex.New(safe...)
j.mu = rwmutex.New(option.Safe)
return j
}
@ -99,42 +111,133 @@ func Load(path string, safe ...bool) (*Json, error) {
} else {
path = p
}
return doLoadContent(gfile.Ext(path), gfile.GetBytesWithCache(path), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption(gfile.Ext(path), gfile.GetBytesWithCache(path), option)
}
// LoadJson creates a Json object from given JSON format content.
func LoadJson(data interface{}, safe ...bool) (*Json, error) {
return doLoadContent("json", gconv.Bytes(data), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption("json", gconv.Bytes(data), option)
}
// LoadXml creates a Json object from given XML format content.
func LoadXml(data interface{}, safe ...bool) (*Json, error) {
return doLoadContent("xml", gconv.Bytes(data), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption("xml", gconv.Bytes(data), option)
}
// LoadIni creates a Json object from given INI format content.
func LoadIni(data interface{}, safe ...bool) (*Json, error) {
return doLoadContent("ini", gconv.Bytes(data), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption("ini", gconv.Bytes(data), option)
}
// LoadYaml creates a Json object from given YAML format content.
func LoadYaml(data interface{}, safe ...bool) (*Json, error) {
return doLoadContent("yaml", gconv.Bytes(data), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption("yaml", gconv.Bytes(data), option)
}
// LoadToml creates a Json object from given TOML format content.
func LoadToml(data interface{}, safe ...bool) (*Json, error) {
return doLoadContent("toml", gconv.Bytes(data), safe...)
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption("toml", gconv.Bytes(data), option)
}
// LoadContent creates a Json object from given content, it checks the data type of <content>
// automatically, supporting data content type as follows:
// JSON, XML, INI, YAML and TOML.
func LoadContent(data interface{}, safe ...bool) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return New(nil, safe...), nil
}
return LoadContentType(checkDataType(content), content, safe...)
}
// LoadContentType creates a Json object from given type and content,
// supporting data content type as follows:
// JSON, XML, INI, YAML and TOML.
func LoadContentType(dataType string, data interface{}, safe ...bool) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return New(nil, safe...), nil
}
//ignore UTF8-BOM
if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF {
content = content[3:]
}
option := Option{}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOption(dataType, content, option)
}
// IsValidDataType checks and returns whether given <dataType> a valid data type for loading.
func IsValidDataType(dataType string) bool {
if dataType == "" {
return false
}
if dataType[0] == '.' {
dataType = dataType[1:]
}
switch dataType {
case "json", "js", "xml", "yaml", "yml", "toml", "ini":
return true
}
return false
}
func loadContentWithOption(data interface{}, option Option) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return NewWithOption(nil, option), nil
}
return loadContentTypeWithOption(checkDataType(content), content, option)
}
func loadContentTypeWithOption(dataType string, data interface{}, option Option) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return NewWithOption(nil, option), nil
}
//ignore UTF8-BOM
if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF {
content = content[3:]
}
return doLoadContentWithOption(dataType, content, option)
}
// doLoadContent creates a Json object from given content.
// It supports data content type as follows:
// JSON, XML, INI, YAML and TOML.
func doLoadContent(dataType string, data []byte, safe ...bool) (*Json, error) {
var err error
var result interface{}
func doLoadContentWithOption(dataType string, data []byte, option Option) (*Json, error) {
var (
err error
result interface{}
)
if len(data) == 0 {
return New(nil, safe...), nil
return NewWithOption(nil, option), nil
}
if dataType == "" {
dataType = checkDataType(data)
@ -167,10 +270,9 @@ func doLoadContent(dataType string, data []byte, safe ...bool) (*Json, error) {
return nil, err
}
decoder := json.NewDecoder(bytes.NewReader(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 option.StrNumber {
decoder.UseNumber()
}
if err := decoder.Decode(&result); err != nil {
return nil, err
}
@ -178,48 +280,7 @@ func doLoadContent(dataType string, data []byte, safe ...bool) (*Json, error) {
case string, []byte:
return nil, fmt.Errorf(`json decoding failed for content: %s`, string(data))
}
return New(result, safe...), nil
}
// LoadContent creates a Json object from given content, it checks the data type of <content>
// automatically, supporting data content type as follows:
// JSON, XML, INI, YAML and TOML.
func LoadContent(data interface{}, safe ...bool) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return New(nil, safe...), nil
}
return LoadContentType(checkDataType(content), content, safe...)
}
// LoadContentType creates a Json object from given type and content,
// supporting data content type as follows:
// JSON, XML, INI, YAML and TOML.
func LoadContentType(dataType string, data interface{}, safe ...bool) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return New(nil, safe...), nil
}
//ignore UTF8-BOM
if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF {
content = content[3:]
}
return doLoadContent(dataType, content, safe...)
}
// IsValidDataType checks and returns whether given <dataType> a valid data type for loading.
func IsValidDataType(dataType string) bool {
if dataType == "" {
return false
}
if dataType[0] == '.' {
dataType = dataType[1:]
}
switch dataType {
case "json", "js", "xml", "yaml", "yml", "toml", "ini":
return true
}
return false
return NewWithOption(result, option), nil
}
// checkDataType automatically checks and returns the data type for <content>.

View File

@ -466,7 +466,20 @@ func Test_Basic(t *testing.T) {
})
}
func Test_IsNil(t *testing.T) {
func TestJson_Var(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
data := []byte("[9223372036854775807, 9223372036854775806]")
array := gjson.New(data).Var().Array()
t.Assert(array, []uint64{9223372036854776000, 9223372036854776000})
})
gtest.C(t, func(t *gtest.T) {
data := []byte("[9223372036854775807, 9223372036854775806]")
array := gjson.NewWithOption(data, gjson.Option{StrNumber: true}).Var().Array()
t.Assert(array, []uint64{9223372036854775807, 9223372036854775806})
})
}
func TestJson_IsNil(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
j := gjson.New(nil)
t.Assert(j.IsNil(), true)

View File

@ -13,7 +13,7 @@ import (
"github.com/gogf/gf/test/gtest"
)
func Test_Load_NewWithTag(t *testing.T) {
func Test_NewWithTag(t *testing.T) {
type User struct {
Age int `xml:"age-xml" json:"age-json"`
Name string `xml:"name-xml" json:"name-json"`
@ -48,7 +48,7 @@ func Test_Load_NewWithTag(t *testing.T) {
})
}
func Test_Load_New_CustomStruct(t *testing.T) {
func Test_New_CustomStruct(t *testing.T) {
type Base struct {
Id int
}
@ -70,7 +70,7 @@ func Test_Load_New_CustomStruct(t *testing.T) {
})
}
func Test_Load_New_HierarchicalStruct(t *testing.T) {
func Test_New_HierarchicalStruct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type Me struct {
Name string `json:"name"`
@ -97,3 +97,16 @@ func Test_Load_New_HierarchicalStruct(t *testing.T) {
t.Assert(j.MustToJsonString(), `{"children":[{"children":null,"name":"Bean"},{"children":null,"name":"Sam"}],"name":"john","score":100}`)
})
}
func Test_NewWithOption(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
data := []byte("[9223372036854775807, 9223372036854775806]")
array := gjson.New(data).Array()
t.Assert(array, []uint64{9223372036854776000, 9223372036854776000})
})
gtest.C(t, func(t *gtest.T) {
data := []byte("[9223372036854775807, 9223372036854775806]")
array := gjson.NewWithOption(data, gjson.Option{StrNumber: true}).Array()
t.Assert(array, []uint64{9223372036854775807, 9223372036854775806})
})
}

View File

@ -76,7 +76,7 @@ func Test_GetScanDeep(t *testing.T) {
})
}
func Test_ToScan(t *testing.T) {
func Test_Scan1(t *testing.T) {
type User struct {
Name string
Score float64
@ -84,7 +84,7 @@ func Test_ToScan(t *testing.T) {
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
gtest.C(t, func(t *gtest.T) {
var users []User
err := j.ToScan(&users)
err := j.Scan(&users)
t.Assert(err, nil)
t.Assert(users, []User{
{
@ -99,7 +99,7 @@ func Test_ToScan(t *testing.T) {
})
}
func Test_ToScanDeep(t *testing.T) {
func Test_Scan2(t *testing.T) {
type User struct {
Name string
Score float64
@ -107,7 +107,7 @@ func Test_ToScanDeep(t *testing.T) {
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
gtest.C(t, func(t *gtest.T) {
var users []User
err := j.ToScanDeep(&users)
err := j.Scan(&users)
t.Assert(err, nil)
t.Assert(users, []User{
{
@ -122,7 +122,7 @@ func Test_ToScanDeep(t *testing.T) {
})
}
func Test_ToStruct1(t *testing.T) {
func Test_Struct1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type BaseInfoItem struct {
IdCardNumber string `db:"id_card_number" json:"idCardNumber" field:"id_card_number"`
@ -198,12 +198,12 @@ func Test_ToStruct1(t *testing.T) {
data := new(UserCollectionAddReq)
j, err := gjson.LoadJson(jsonContent)
t.Assert(err, nil)
err = j.ToStruct(data)
err = j.Struct(data)
t.Assert(err, nil)
})
}
func Test_ToStruct(t *testing.T) {
func Test_Struct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type Item struct {
Title string `json:"title"`
@ -231,7 +231,7 @@ func Test_ToStruct(t *testing.T) {
t.Assert(j.GetBool("items"), false)
t.Assert(j.GetArray("items"), nil)
m := new(M)
err = j.ToStruct(m)
err = j.Struct(m)
t.Assert(err, nil)
t.AssertNE(m.Me, nil)
t.Assert(m.Me["day"], "20009")
@ -239,7 +239,7 @@ func Test_ToStruct(t *testing.T) {
})
}
func Test_ToStruct_Complicated(t *testing.T) {
func Test_Struct_Complicated(t *testing.T) {
type CertInfo struct {
UserRealName string `json:"userRealname,omitempty"`
IdentType string `json:"identType,omitempty"`
@ -290,7 +290,7 @@ func Test_ToStruct_Complicated(t *testing.T) {
j, err := gjson.LoadContent(jsonContent)
t.Assert(err, nil)
var response = new(Response)
err = j.ToStruct(response)
err = j.Struct(response)
t.Assert(err, nil)
t.Assert(len(response.CertList), 3)
t.Assert(response.CertList[0].CertID, 2023313)