mirror of
https://gitee.com/johng/gf
synced 2026-07-07 14:25:17 +08:00
gjson updates
This commit is contained in:
@ -67,7 +67,7 @@ func (v *Var) Time(format...string) time.Time {
|
||||
|
||||
// TimeDuration converts and returns <v> as time.Duration.
|
||||
// If value of <v> is string, then it uses time.ParseDuration for conversion.
|
||||
func (v *Var) TimeDuration() time.Duration {
|
||||
func (v *Var) Duration() time.Duration {
|
||||
return gconv.Duration(v.Val())
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import (
|
||||
"github.com/gogf/gf/g/os/gfcache"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// New creates a Json object with any variable type of <data>,
|
||||
@ -29,31 +30,45 @@ import (
|
||||
func New(data interface{}, unsafe...bool) *Json {
|
||||
j := (*Json)(nil)
|
||||
switch data.(type) {
|
||||
case map[string]interface{}, []interface{}, nil:
|
||||
j = &Json {
|
||||
p : &data,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false ,
|
||||
}
|
||||
case string, []byte:
|
||||
j, _ = LoadContent(gconv.Bytes(data))
|
||||
default:
|
||||
v := (interface{})(nil)
|
||||
if m := gconv.Map(data); m != nil {
|
||||
v = m
|
||||
j = &Json {
|
||||
p : &v,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false,
|
||||
}
|
||||
if r, err := LoadContent(gconv.Bytes(data)); err == nil {
|
||||
j = r
|
||||
} else {
|
||||
v = gconv.Interfaces(data)
|
||||
j = &Json {
|
||||
p : &v,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false,
|
||||
}
|
||||
j = &Json {
|
||||
p : &data,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false ,
|
||||
}
|
||||
}
|
||||
default:
|
||||
rv := reflect.ValueOf(data)
|
||||
kind := rv.Kind()
|
||||
switch kind {
|
||||
case reflect.Slice: fallthrough
|
||||
case reflect.Array:
|
||||
i := interface{}(nil)
|
||||
i = gconv.Interfaces(data)
|
||||
j = &Json {
|
||||
p : &i,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false ,
|
||||
}
|
||||
case reflect.Map: fallthrough
|
||||
case reflect.Struct:
|
||||
i := interface{}(nil)
|
||||
i = gconv.Map(data)
|
||||
j = &Json {
|
||||
p : &i,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false ,
|
||||
}
|
||||
default:
|
||||
j = &Json {
|
||||
p : &data,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : false ,
|
||||
}
|
||||
}
|
||||
}
|
||||
j.mu = rwmutex.New(unsafe...)
|
||||
return j
|
||||
|
||||
63
g/encoding/gjson/gjson_func.go
Normal file
63
g/encoding/gjson/gjson_func.go
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2017 gf Author(https://github.com/gogf/gf). 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 gjson
|
||||
|
||||
//func MarshalOrdered(value interface{}) ([]byte, error) {
|
||||
// buffer := bytes.NewBuffer(nil)
|
||||
// rv := reflect.ValueOf(value)
|
||||
// kind := rv.Kind()
|
||||
// if kind == reflect.Ptr {
|
||||
// rv = rv.Elem()
|
||||
// kind = rv.Kind()
|
||||
// }
|
||||
// switch kind {
|
||||
// case reflect.Slice: fallthrough
|
||||
// case reflect.Array:
|
||||
// buffer.WriteByte('[')
|
||||
// length := rv.Len()
|
||||
// for i := 0; i < length; i++ {
|
||||
// if p, err := MarshalOrdered(rv.Index(i).Interface()); err != nil {
|
||||
// return nil, err
|
||||
// } else {
|
||||
// buffer.Write(p)
|
||||
// if i < length - 1 {
|
||||
// buffer.WriteByte(',')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// buffer.WriteByte(']')
|
||||
// case reflect.Map: fallthrough
|
||||
// case reflect.Struct:
|
||||
// m := gconv.Map(value, "json")
|
||||
// keys := make([]string, len(m))
|
||||
// index := 0
|
||||
// for key := range m {
|
||||
// keys[index] = key
|
||||
// index++
|
||||
// }
|
||||
// sort.Strings(keys)
|
||||
// buffer.WriteByte('{')
|
||||
// for i, key := range keys {
|
||||
// if p, err := MarshalOrdered(m[key]); err != nil {
|
||||
// return nil, err
|
||||
// } else {
|
||||
// buffer.WriteString(fmt.Sprintf(`"%s":%s`, key, string(p)))
|
||||
// if i < index - 1 {
|
||||
// buffer.WriteByte(',')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// buffer.WriteByte('}')
|
||||
// default:
|
||||
// if p, err := json.Marshal(value); err != nil {
|
||||
// return nil, err
|
||||
// } else {
|
||||
// buffer.Write(p)
|
||||
// }
|
||||
// }
|
||||
// return buffer.Bytes(), nil
|
||||
//}
|
||||
@ -225,29 +225,42 @@ func Test_Len(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_Append(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
gtest.Assert(p.Get("a"), g.Slice{1, 2})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
gtest.Assert(p.Get("a"), g.Map{
|
||||
"b" : g.Slice{1},
|
||||
"c" : g.Slice{2},
|
||||
})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Set("a", 1)
|
||||
err := p.Append("a", 2)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.Assert(p.Get("a"), 1)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
gtest.Assert(p.Get("a"), g.Slice{1, 2})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
gtest.Assert(p.Get("a"), g.Map{
|
||||
"b" : g.Slice{1},
|
||||
"c" : g.Slice{2},
|
||||
})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New(nil)
|
||||
p.Set("a", 1)
|
||||
err := p.Append("a", 2)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.Assert(p.Get("a"), 1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func TestJson_ToJson(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New("1")
|
||||
s, e := p.ToJsonString()
|
||||
gtest.Assert(e, nil)
|
||||
gtest.Assert(s, "1")
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gjson.New("a")
|
||||
s, e := p.ToJsonString()
|
||||
gtest.Assert(e, nil)
|
||||
gtest.Assert(s, `"a"`)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -18,10 +18,18 @@ func (p *Parser) ToJson() ([]byte, error) {
|
||||
return p.json.ToJson()
|
||||
}
|
||||
|
||||
func (p *Parser) ToJsonString() (string, error) {
|
||||
return p.json.ToJsonString()
|
||||
}
|
||||
|
||||
func (p *Parser) ToJsonIndent() ([]byte, error) {
|
||||
return p.json.ToJsonIndent()
|
||||
}
|
||||
|
||||
func (p *Parser) ToJsonIndentString() (string, error) {
|
||||
return p.json.ToJsonIndentString()
|
||||
}
|
||||
|
||||
func (p *Parser) ToYaml() ([]byte, error) {
|
||||
return p.json.ToYaml()
|
||||
}
|
||||
@ -42,8 +50,16 @@ func VarToJson(value interface{}) ([]byte, error) {
|
||||
return New(value).ToJson()
|
||||
}
|
||||
|
||||
func VarToJsonString(value interface{}) (string, error) {
|
||||
return New(value).ToJsonString()
|
||||
}
|
||||
|
||||
func VarToJsonIndent(value interface{}) ([]byte, error) {
|
||||
return New(value).ToJsonIndent()
|
||||
return New(value).ToJsonIndent()
|
||||
}
|
||||
|
||||
func VarToJsonIndentString(value interface{}) (string, error) {
|
||||
return New(value).ToJsonIndentString()
|
||||
}
|
||||
|
||||
func VarToYaml(value interface{}) ([]byte, error) {
|
||||
|
||||
@ -114,7 +114,7 @@ func (s *Session) Get(key string, def...interface{}) interface{} {
|
||||
|
||||
// 获取SESSION,建议都用该方法获取参数
|
||||
func (s *Session) GetVar(key string, def...interface{}) *gvar.Var {
|
||||
return gvar.NewRead(s.Get(key, def...), true)
|
||||
return gvar.New(s.Get(key, def...), true)
|
||||
}
|
||||
|
||||
// 删除session
|
||||
|
||||
@ -15,10 +15,9 @@ import (
|
||||
|
||||
// Map converts any variable <i> to map[string]interface{}.
|
||||
// If the parameter <i> is not a map type, then the conversion will fail and returns nil.
|
||||
// If <i> is a struct object, the second parameter noTagCheck means that
|
||||
// the json tag is not detected,
|
||||
// otherwise the json tag will be used as the map key name.
|
||||
func Map(value interface{}, noTagCheck...bool) map[string]interface{} {
|
||||
// If <i> is a struct object, the second parameter <tags> specifies the most priority
|
||||
// tags that will be detected, otherwise it detects the tags in order of: gconv, json.
|
||||
func Map(value interface{}, tags...string) map[string]interface{} {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
@ -52,7 +51,6 @@ func Map(value interface{}, noTagCheck...bool) map[string]interface{} {
|
||||
for k, v := range value.(map[interface{}]float64) {
|
||||
m[String(k)] = v
|
||||
}
|
||||
|
||||
case map[string]bool:
|
||||
for k, v := range value.(map[string]bool) {
|
||||
m[k] = v
|
||||
@ -102,21 +100,32 @@ func Map(value interface{}, noTagCheck...bool) map[string]interface{} {
|
||||
m[String(k.Interface())] = rv.MapIndex(k).Interface()
|
||||
}
|
||||
case reflect.Struct:
|
||||
rt := rv.Type()
|
||||
name := ""
|
||||
rt := rv.Type()
|
||||
name := ""
|
||||
gconvTag := "gconv"
|
||||
tagArray := []string{gconvTag, "json"}
|
||||
switch len(tags) {
|
||||
case 0:
|
||||
// No need handle.
|
||||
case 1:
|
||||
tagArray = strings.Split(tags[0], ",")
|
||||
default:
|
||||
tagArray = tags
|
||||
}
|
||||
if gstr.SearchArray(tagArray, gconvTag) < 0 {
|
||||
tagArray = append(tagArray, gconvTag)
|
||||
}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
// Only convert the public attributes.
|
||||
fieldName := rt.Field(i).Name
|
||||
if !gstr.IsLetterUpper(fieldName[0]) {
|
||||
continue
|
||||
}
|
||||
name = ""
|
||||
// Tag check, supporting "gconv" and "json" tag,
|
||||
// "gconv" has the high priority to use.
|
||||
if len(noTagCheck) == 0 || !noTagCheck[0] {
|
||||
tag := rt.Field(i).Tag
|
||||
if name = tag.Get("gconv"); name == "" {
|
||||
name = tag.Get("json")
|
||||
name = ""
|
||||
fieldTag := rt.Field(i).Tag
|
||||
for _, tag := range tagArray {
|
||||
if name = fieldTag.Get(tag); name != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
if name == "" {
|
||||
|
||||
@ -8,17 +8,16 @@
|
||||
package gutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/internal/empty"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/internal/empty"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// 格式化打印变量
|
||||
// Dump prints variables <i...> to stdout with more manually readable.
|
||||
func Dump(i...interface{}) {
|
||||
s := Export(i...)
|
||||
if s != "" {
|
||||
@ -26,25 +25,16 @@ func Dump(i...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化导出变量
|
||||
// Export returns variables <i...> as a string with more manually readable.
|
||||
func Export(i...interface{}) string {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
for _, v := range i {
|
||||
if b, ok := v.([]byte); ok {
|
||||
buffer.Write(b)
|
||||
} else {
|
||||
// 主要针对 map[interface{}]* 进行处理,json无法进行encode,
|
||||
// 这里强制对所有map进行反射处理转换
|
||||
refValue := reflect.ValueOf(v)
|
||||
if refValue.Kind() == reflect.Map {
|
||||
m := make(map[string]interface{})
|
||||
keys := refValue.MapKeys()
|
||||
for _, k := range keys {
|
||||
m[gconv.String(k.Interface())] = refValue.MapIndex(k).Interface()
|
||||
}
|
||||
v = m
|
||||
if m := gconv.Map(v); m != nil {
|
||||
v = m
|
||||
}
|
||||
// JSON格式化
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetEscapeHTML(false)
|
||||
encoder.SetIndent("", "\t")
|
||||
@ -56,7 +46,7 @@ func Export(i...interface{}) string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// 打印完整的调用回溯信息
|
||||
// PrintBacktrace prints the caller backtrace to stdout.
|
||||
func PrintBacktrace() {
|
||||
index := 1
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
@ -71,12 +61,12 @@ func PrintBacktrace() {
|
||||
fmt.Print(buffer.String())
|
||||
}
|
||||
|
||||
// 抛出一个异常
|
||||
// Throw throws out an exception, which can be caught be TryCatch or recover.
|
||||
func Throw(exception interface{}) {
|
||||
panic(exception)
|
||||
}
|
||||
|
||||
// try...catch...
|
||||
// TryCatch implements try...catch... logistics.
|
||||
func TryCatch(try func(), catch ... func(exception interface{})) {
|
||||
if len(catch) > 0 {
|
||||
defer func() {
|
||||
@ -88,13 +78,9 @@ func TryCatch(try func(), catch ... func(exception interface{})) {
|
||||
try()
|
||||
}
|
||||
|
||||
// IsEmpty checks given value empty or not.
|
||||
// false: integer(0), bool(false), slice/map(len=0), nil;
|
||||
// true : other.
|
||||
//
|
||||
// 判断给定的变量是否为空。
|
||||
// 整型为0, 布尔为false, slice/map长度为0, 其他为nil的情况,都为空。
|
||||
// 为空时返回true,否则返回false。
|
||||
// IsEmpty checks given <value> empty or not.
|
||||
// It returns false if <value> is: integer(0), bool(false), slice/map(len=0), nil;
|
||||
// or else returns true.
|
||||
func IsEmpty(value interface{}) bool {
|
||||
return empty.IsEmpty(value)
|
||||
}
|
||||
|
||||
@ -2,24 +2,38 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtree"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tree := gtree.New(func(v1, v2 interface{}) int {
|
||||
return v1.(int) - v2.(int)
|
||||
})
|
||||
for i := 0; i < 20; i++ {
|
||||
tree.Set(i, i)
|
||||
//b, e := gjson.MarshalOrdered(g.Map{
|
||||
// "a" : 1,
|
||||
// "b" : 2,
|
||||
// "c" : 3,
|
||||
//})
|
||||
//fmt.Println(e)
|
||||
//fmt.Println(string(b))
|
||||
|
||||
//m := map[string]interface{}{
|
||||
// "facet_is_special_price":[]string{"1"},
|
||||
// "score_outlet":"0",
|
||||
// "skus":[]string{"DI139BE71WDWDFMX", "DI139BE71WDWDFMX-519406"},
|
||||
// "facet_novelty_two_days":[]string{"0"},
|
||||
// "facet_brand":[]string{"139"},
|
||||
// "sku":[]string{"DI139BE71WDWDFMX"},
|
||||
//}
|
||||
|
||||
for {
|
||||
m := make(map[string]interface{})
|
||||
m["facet_is_special_price"] = []string{"1"}
|
||||
m["score_outlet"] = "0"
|
||||
m["skus"] = []string{"DI139BE71WDWDFMX", "DI139BE71WDWDFMX-519406"}
|
||||
m["facet_novelty_two_days"] = []string{"0"}
|
||||
m["facet_brand"] = []string{"139"}
|
||||
m["sku"] = []string{"DI139BE71WDWDFMX"}
|
||||
fmt.Println(gparser.VarToJsonString(m))
|
||||
time.Sleep(100*time.Millisecond)
|
||||
}
|
||||
tree.Print()
|
||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||
fmt.Println(key)
|
||||
return true
|
||||
})
|
||||
fmt.Println()
|
||||
tree.IteratorDesc(func(key, value interface{}) bool {
|
||||
fmt.Println(key)
|
||||
return true
|
||||
})
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user