diff --git a/container/gvar/gvar.go b/container/gvar/gvar.go index 1f8fd0e4e..1babba781 100644 --- a/container/gvar/gvar.go +++ b/container/gvar/gvar.go @@ -106,11 +106,6 @@ func (v *Var) Int() int { return gconv.Int(v.Val()) } -// Ints converts and returns as []int. -func (v *Var) Ints() []int { - return gconv.Ints(v.Val()) -} - // Int8 converts and returns 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 as []uint. -func (v *Var) Uints() []uint { - return gconv.Uints(v.Val()) -} - // Uint8 converts and returns 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 as []float64. -func (v *Var) Floats() []float64 { - return gconv.Floats(v.Val()) -} - -// Strings converts and returns as []string. -func (v *Var) Strings() []string { - return gconv.Strings(v.Val()) -} - -// Interfaces converts and returns 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 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 as time.Time. // The parameter specifies the format of the time string using gtime, // eg: Y-m-d H:i:s. diff --git a/container/gvar/gvar_slice.go b/container/gvar/gvar_slice.go new file mode 100644 index 000000000..e4c2f5272 --- /dev/null +++ b/container/gvar/gvar_slice.go @@ -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 as []int. +func (v *Var) Ints() []int { + return gconv.Ints(v.Val()) +} + +// Int64s converts and returns as []int64. +func (v *Var) Int64s() []int64 { + return gconv.Int64s(v.Val()) +} + +// Uints converts and returns as []uint. +func (v *Var) Uints() []uint { + return gconv.Uints(v.Val()) +} + +// Uint64s converts and returns 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 as []float32. +func (v *Var) Float32s() []float32 { + return gconv.Float32s(v.Val()) +} + +// Float64s converts and returns as []float64. +func (v *Var) Float64s() []float64 { + return gconv.Float64s(v.Val()) +} + +// Strings converts and returns as []string. +func (v *Var) Strings() []string { + return gconv.Strings(v.Val()) +} + +// Interfaces converts and returns 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 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 +} diff --git a/container/gvar/gvar_z_unit_basic_test.go b/container/gvar/gvar_z_unit_basic_test.go index f3feaf3ed..d46ab188f 100644 --- a/container/gvar/gvar_z_unit_basic_test.go +++ b/container/gvar/gvar_z_unit_basic_test.go @@ -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 diff --git a/container/gvar/gvar_z_unit_json_test.go b/container/gvar/gvar_z_unit_json_test.go index 0c02c80eb..53dc856f3 100644 --- a/container/gvar/gvar_z_unit_json_test.go +++ b/container/gvar/gvar_z_unit_json_test.go @@ -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" diff --git a/container/gvar/gvar_z_unit_list_test.go b/container/gvar/gvar_z_unit_list_test.go index d62a4d24a..eb2cd2314 100644 --- a/container/gvar/gvar_z_unit_list_test.go +++ b/container/gvar/gvar_z_unit_list_test.go @@ -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}, diff --git a/container/gvar/gvar_z_unit_map_test.go b/container/gvar/gvar_z_unit_map_test.go index 30e6c7718..d0b96deb6 100644 --- a/container/gvar/gvar_z_unit_map_test.go +++ b/container/gvar/gvar_z_unit_map_test.go @@ -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"]) + }) +} diff --git a/container/gvar/gvar_z_unit_maptomap_test.go b/container/gvar/gvar_z_unit_maptomap_test.go deleted file mode 100644 index 89350f1d7..000000000 --- a/container/gvar/gvar_z_unit_maptomap_test.go +++ /dev/null @@ -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"]) - }) -} diff --git a/container/gvar/gvar_z_unit_slice_test.go b/container/gvar/gvar_z_unit_slice_test.go new file mode 100644 index 000000000..585b17bbd --- /dev/null +++ b/container/gvar/gvar_z_unit_slice_test.go @@ -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) + }) +} diff --git a/container/gvar/gvar_z_unit_struct_test.go b/container/gvar/gvar_z_unit_struct_test.go index e65c593a3..2164e5ad6 100644 --- a/container/gvar/gvar_z_unit_struct_test.go +++ b/container/gvar/gvar_z_unit_struct_test.go @@ -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 diff --git a/encoding/gjson/gjson.go b/encoding/gjson/gjson.go index 2a16bb9bf..df30d9e75 100644 --- a/encoding/gjson/gjson.go +++ b/encoding/gjson/gjson.go @@ -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 to by . // Note: // 1. If value is nil and removed is true, means deleting this value; diff --git a/encoding/gjson/gjson_api.go b/encoding/gjson/gjson_api.go index 3f74ef6ea..51787f102 100644 --- a/encoding/gjson/gjson_api.go +++ b/encoding/gjson/gjson_api.go @@ -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 is nil. func (j *Json) IsNil() bool { j.mu.RLock() diff --git a/encoding/gjson/gjson_api_new_load.go b/encoding/gjson/gjson_api_new_load.go index b6a711f17..8759f2e71 100644 --- a/encoding/gjson/gjson_api_new_load.go +++ b/encoding/gjson/gjson_api_new_load.go @@ -42,15 +42,27 @@ func New(data interface{}, safe ...bool) *Json { // The parameter 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 , but 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 +// 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 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 -// 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 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 . diff --git a/encoding/gjson/gjson_z_unit_basic_test.go b/encoding/gjson/gjson_z_unit_basic_test.go index 1c5244556..733adea8e 100644 --- a/encoding/gjson/gjson_z_unit_basic_test.go +++ b/encoding/gjson/gjson_z_unit_basic_test.go @@ -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) diff --git a/encoding/gjson/gjson_z_unit_new_test.go b/encoding/gjson/gjson_z_unit_new_test.go index c3051ce26..b4f911379 100644 --- a/encoding/gjson/gjson_z_unit_new_test.go +++ b/encoding/gjson/gjson_z_unit_new_test.go @@ -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}) + }) +} diff --git a/encoding/gjson/gjson_z_unit_struct_test.go b/encoding/gjson/gjson_z_unit_struct_test.go index 046acc194..bd41a366b 100644 --- a/encoding/gjson/gjson_z_unit_struct_test.go +++ b/encoding/gjson/gjson_z_unit_struct_test.go @@ -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)