gjson updates

This commit is contained in:
John
2019-05-11 17:56:14 +08:00
parent bd4c75a98e
commit 664b0c06a6
9 changed files with 225 additions and 109 deletions

View File

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

View File

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

View 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
//}

View File

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

View File

@ -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) {

View File

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

View File

@ -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 == "" {

View File

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

View File

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