improve gstr/gjson/gconv

This commit is contained in:
John
2019-07-18 18:59:49 +08:00
parent a4abac4916
commit f465b478d6
12 changed files with 165 additions and 73 deletions

View File

@ -21,7 +21,7 @@ addons:
- local
before_install:
- pwd
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
install:
- cat /etc/hosts

View File

@ -10,6 +10,8 @@ import (
"fmt"
"time"
"github.com/gogf/gf/g/util/gutil"
"github.com/gogf/gf/g/container/gvar"
"github.com/gogf/gf/g/os/gtime"
"github.com/gogf/gf/g/util/gconv"
@ -22,6 +24,13 @@ func (j *Json) Value() interface{} {
return *(j.p)
}
// IsNil checks whether the value pointed by <j> is nil.
func (j *Json) IsNil() bool {
j.mu.RLock()
defer j.mu.RUnlock()
return j.p == nil || *(j.p) == nil
}
// Get returns value by specified <pattern>.
// It returns all values of current Json object, if <pattern> is empty or not specified.
// It returns nil if no value found by <pattern>.
@ -67,11 +76,7 @@ func (j *Json) GetMap(pattern string, def ...interface{}) map[string]interface{}
// GetJson gets the value by specified <pattern>,
// and converts it to a un-concurrent-safe Json object.
func (j *Json) GetJson(pattern string, def ...interface{}) *Json {
result := j.Get(pattern, def...)
if result != nil {
return New(result, true)
}
return nil
return New(j.Get(pattern, def...), true)
}
// GetJsons gets the value by specified <pattern>,
@ -257,6 +262,7 @@ func (j *Json) Append(pattern string, value interface{}) error {
// GetToVar gets the value by specified <pattern>,
// and converts it to specified golang variable <v>.
// The <pointer> should be a pointer type.
// Deprecated.
func (j *Json) GetToVar(pattern string, pointer interface{}) error {
r := j.Get(pattern)
if r != nil {
@ -342,13 +348,15 @@ func (j *Json) ToStructsDeep(pointer interface{}) error {
}
// Dump prints current Json object with more manually readable.
func (j *Json) Dump() error {
func (j *Json) Dump() {
j.mu.RLock()
defer j.mu.RUnlock()
if b, err := j.ToJsonIndent(); err != nil {
return err
} else {
fmt.Println(string(b))
}
return nil
gutil.Dump(*j.p)
}
// Export returns <j> as a string with more manually readable.
func (j *Json) Export() string {
j.mu.RLock()
defer j.mu.RUnlock()
return gutil.Export(*j.p)
}

View File

@ -7,10 +7,11 @@
package gjson_test
import (
"testing"
"github.com/gogf/gf/g"
"github.com/gogf/gf/g/encoding/gjson"
"github.com/gogf/gf/g/test/gtest"
"testing"
)
func Test_New(t *testing.T) {
@ -361,7 +362,7 @@ func Test_Convert2(t *testing.T) {
err := j.ToStruct(&name)
gtest.Assert(err, nil)
gtest.Assert(name.Name, "gf")
err = j.Dump()
j.Dump()
gtest.Assert(err, nil)
j = gjson.New(`{"person":{"name":"gf"}}`)
@ -370,7 +371,7 @@ func Test_Convert2(t *testing.T) {
gtest.Assert(name.Name, "gf")
j = gjson.New(`{"name":"gf""}`)
err = j.Dump()
j.Dump()
gtest.Assert(err, nil)
j = gjson.New(`[1,2,3]`)
@ -459,3 +460,10 @@ func Test_Basic(t *testing.T) {
})
}
func Test_IsNil(t *testing.T) {
gtest.Case(t, func() {
j := gjson.New(nil)
gtest.Assert(j.IsNil(), true)
})
}

View File

@ -7,9 +7,10 @@
package gparser
import (
"time"
"github.com/gogf/gf/g/container/gvar"
"github.com/gogf/gf/g/os/gtime"
"time"
)
// Val returns the value.
@ -141,6 +142,7 @@ func (p *Parser) GetGTime(pattern string, format ...string) *gtime.Time {
// GetToVar gets the value by specified <pattern>,
// and converts it to specified golang variable <v>.
// The <v> should be a pointer type.
// Deprecated.
func (p *Parser) GetToVar(pattern string, pointer interface{}) error {
return p.json.GetToVar(pattern, pointer)
}
@ -216,7 +218,23 @@ func (p *Parser) ToStruct(pointer interface{}) error {
return p.json.ToStruct(pointer)
}
// Dump prints current Json object with more manually readable.
func (p *Parser) Dump() error {
return p.json.Dump()
func (p *Parser) ToStructDeep(pointer interface{}) error {
return p.json.ToStructDeep(pointer)
}
func (p *Parser) ToStructs(pointer interface{}) error {
return p.json.ToStructs(pointer)
}
func (p *Parser) ToStructsDeep(pointer interface{}) error {
return p.json.ToStructsDeep(pointer)
}
// Dump prints current Json object with more manually readable.
func (p *Parser) Dump() {
p.json.Dump()
}
func (p *Parser) Export() string {
return p.json.Export()
}

View File

@ -7,7 +7,6 @@
package gins_test
import (
"fmt"
"testing"
"time"
@ -60,7 +59,7 @@ test = "v=2"
time.Sleep(500 * time.Millisecond)
gtest.Case(t, func() {
fmt.Println("gins Test_Database", gins.Config().Get("test"))
//fmt.Println("gins Test_Database", gins.Config().Get("test"))
dbDefault := gins.Database()
dbTest := gins.Database("test")

View File

@ -0,0 +1,60 @@
// Copyright 2019 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 strutils provides some string functions for internal usage.
package strutils
import "strings"
// IsLetterUpper tests whether the given byte b is in upper case.
func IsLetterUpper(b byte) bool {
if b >= byte('A') && b <= byte('Z') {
return true
}
return false
}
// IsLetterLower tests whether the given byte b is in lower case.
func IsLetterLower(b byte) bool {
if b >= byte('a') && b <= byte('z') {
return true
}
return false
}
// IsNumeric tests whether the given string s is numeric.
func IsNumeric(s string) bool {
length := len(s)
if length == 0 {
return false
}
for i := 0; i < len(s); i++ {
if s[i] < byte('0') || s[i] > byte('9') {
return false
}
}
return true
}
// UcFirst returns a copy of the string s with the first letter mapped to its upper case.
func UcFirst(s string) string {
if len(s) == 0 {
return s
}
if IsLetterLower(s[0]) {
return string(s[0]-32) + s[1:]
}
return s
}
// ReplaceByMap returns a copy of <origin>,
// which is replaced by a map in unordered way, case-sensitively.
func ReplaceByMap(origin string, replaces map[string]string) string {
for k, v := range replaces {
origin = strings.Replace(origin, k, v, -1)
}
return origin
}

View File

@ -8,10 +8,10 @@ package gtime
import (
"bytes"
"github.com/gogf/gf/g/text/gregex"
"github.com/gogf/gf/g/text/gstr"
"strconv"
"strings"
"github.com/gogf/gf/g/text/gregex"
)
var (
@ -110,9 +110,15 @@ func (t *Time) Format(format string) string {
// 有几个转换的符号需要特殊处理
switch runes[i] {
case 'j':
buffer.WriteString(gstr.ReplaceByArray(result, []string{"=j=0", "", "=j=", ""}))
for _, s := range []string{"=j=0", "=j="} {
result = strings.Replace(result, s, "", -1)
}
buffer.WriteString(result)
case 'G':
buffer.WriteString(gstr.ReplaceByArray(result, []string{"=G=0", "", "=G=", ""}))
for _, s := range []string{"=G=0", "=G="} {
result = strings.Replace(result, s, "", -1)
}
buffer.WriteString(result)
case 'u':
buffer.WriteString(strings.Replace(result, "=u=.", "", -1))
case 'w':

View File

@ -10,12 +10,17 @@ package gstr
import (
"bytes"
"fmt"
"github.com/gogf/gf/g/util/grand"
"math"
"strconv"
"strings"
"unicode"
"unicode/utf8"
"github.com/gogf/gf/g/internal/strutils"
"github.com/gogf/gf/g/util/gconv"
"github.com/gogf/gf/g/util/grand"
)
// Replace returns a copy of the string <origin>
@ -93,10 +98,7 @@ func ReplaceIByArray(origin string, array []string) string {
// ReplaceByMap returns a copy of <origin>,
// which is replaced by a map in unordered way, case-sensitively.
func ReplaceByMap(origin string, replaces map[string]string) string {
for k, v := range replaces {
origin = Replace(origin, k, v)
}
return origin
return strutils.ReplaceByMap(origin, replaces)
}
// ReplaceIByMap returns a copy of <origin>,
@ -120,13 +122,7 @@ func ToUpper(s string) string {
// UcFirst returns a copy of the string s with the first letter mapped to its upper case.
func UcFirst(s string) string {
if len(s) == 0 {
return s
}
if IsLetterLower(s[0]) {
return string(s[0]-32) + s[1:]
}
return s
return strutils.UcFirst(s)
}
// LcFirst returns a copy of the string s with the first letter mapped to its lower case.
@ -147,40 +143,25 @@ func UcWords(str string) string {
// IsLetterLower tests whether the given byte b is in lower case.
func IsLetterLower(b byte) bool {
if b >= byte('a') && b <= byte('z') {
return true
}
return false
return strutils.IsLetterLower(b)
}
// IsLetterUpper tests whether the given byte b is in upper case.
func IsLetterUpper(b byte) bool {
if b >= byte('A') && b <= byte('Z') {
return true
}
return false
return strutils.IsLetterUpper(b)
}
// IsNumeric tests whether the given string s is numeric.
func IsNumeric(s string) bool {
length := len(s)
if length == 0 {
return false
}
for i := 0; i < len(s); i++ {
if s[i] < byte('0') || s[i] > byte('9') {
return false
}
}
return true
return strutils.IsNumeric(s)
}
// SubStr returns a portion of string <str> specified by the <start> and <length> parameters.
func SubStr(str string, start int, length ...int) (substr string) {
// 将字符串的转换成[]rune
// Converting to []rune to support unicode.
rs := []rune(str)
lth := len(rs)
// 简单的越界判断
// Simple border checks.
if start < 0 {
start = 0
}
@ -197,7 +178,6 @@ func SubStr(str string, start int, length ...int) (substr string) {
if end > lth {
end = lth
}
// 返回子串
return string(rs[start:end])
}
@ -468,6 +448,14 @@ func Join(array []string, sep string) string {
return strings.Join(array, sep)
}
// JoinAny concatenates the elements of a to create a single string. The separator string
// sep is placed between elements in the resulting string.
//
// The parameter <array> can be any type of slice.
func JoinAny(array interface{}, sep string) string {
return strings.Join(gconv.Strings(array), sep)
}
// Explode splits string <str> by a string <delimiter>, to an array.
// See http://php.net/manual/en/function.explode.php.
func Explode(delimiter, str string) []string {

View File

@ -11,7 +11,7 @@ import (
"strings"
"github.com/gogf/gf/g/internal/empty"
"github.com/gogf/gf/g/text/gstr"
"github.com/gogf/gf/g/internal/strutils"
)
// Map converts any variable <value> to map[string]interface{}.
@ -116,7 +116,7 @@ func Map(value interface{}, tags ...string) map[string]interface{} {
for i := 0; i < rv.NumField(); i++ {
// Only convert the public attributes.
fieldName := rt.Field(i).Name
if !gstr.IsLetterUpper(fieldName[0]) {
if !strutils.IsLetterUpper(fieldName[0]) {
continue
}
name = ""

View File

@ -11,7 +11,7 @@ import (
"fmt"
"reflect"
"github.com/gogf/gf/g/text/gstr"
"github.com/gogf/gf/g/internal/strutils"
)
// SliceInt is alias of Ints.
@ -357,7 +357,7 @@ func Interfaces(i interface{}) []interface{} {
rt := rv.Type()
for i := 0; i < rv.NumField(); i++ {
// Only public attributes.
if !gstr.IsLetterUpper(rt.Field(i).Name[0]) {
if !strutils.IsLetterUpper(rt.Field(i).Name[0]) {
continue
}
array = append(array, rv.Field(i).Interface())
@ -447,6 +447,10 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma
}
switch kind {
case reflect.Slice, reflect.Array:
// If <params> is an empty slice, no conversion.
if rv.Len() == 0 {
return nil
}
array := reflect.MakeSlice(pointerRt.Elem(), rv.Len(), rv.Len())
itemType := array.Index(0).Type()
for i := 0; i < rv.Len(); i++ {

View File

@ -13,7 +13,7 @@ import (
"strings"
"github.com/gogf/gf/g/internal/structs"
"github.com/gogf/gf/g/text/gstr"
"github.com/gogf/gf/g/internal/strutils"
)
// Struct maps the params key-value pairs to the corresponding struct object's properties.
@ -92,7 +92,7 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin
elemType := elem.Type()
for i := 0; i < elem.NumField(); i++ {
// Only do converting to public attributes.
if !gstr.IsLetterUpper(elemType.Field(i).Name[0]) {
if !strutils.IsLetterUpper(elemType.Field(i).Name[0]) {
continue
}
attrMap[elemType.Field(i).Name] = struct{}{}
@ -100,8 +100,8 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin
for mapK, mapV := range paramsMap {
name := ""
for _, checkName := range []string{
gstr.UcFirst(mapK),
gstr.ReplaceByMap(mapK, map[string]string{
strutils.UcFirst(mapK),
strutils.ReplaceByMap(mapK, map[string]string{
"_": "",
"-": "",
" ": "",
@ -118,7 +118,7 @@ func Struct(params interface{}, pointer interface{}, mapping ...map[string]strin
name = value
break
}
if strings.EqualFold(checkName, gstr.Replace(value, "_", "")) {
if strings.EqualFold(checkName, strings.Replace(value, "_", "", -1)) {
name = value
break
}
@ -159,7 +159,7 @@ func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]s
rt := rv.Type()
for i := 0; i < rv.NumField(); i++ {
// Only do converting to public attributes.
if !gstr.IsLetterUpper(rt.Field(i).Name[0]) {
if !strutils.IsLetterUpper(rt.Field(i).Name[0]) {
continue
}
trv := rv.Field(i)

View File

@ -7,9 +7,10 @@
package gconv
import (
"github.com/gogf/gf/g/os/gtime"
"github.com/gogf/gf/g/text/gstr"
"time"
"github.com/gogf/gf/g/internal/strutils"
"github.com/gogf/gf/g/os/gtime"
)
// Time converts <i> to time.Time.
@ -22,7 +23,7 @@ func Time(i interface{}, format ...string) time.Time {
// If <i> is numeric, then it converts <i> as nanoseconds.
func Duration(i interface{}) time.Duration {
s := String(i)
if !gstr.IsNumeric(s) {
if !strutils.IsNumeric(s) {
d, _ := time.ParseDuration(s)
return d
}
@ -43,7 +44,7 @@ func GTime(i interface{}, format ...string) *gtime.Time {
t, _ := gtime.StrToTimeFormat(s, format[0])
return t
}
if gstr.IsNumeric(s) {
if strutils.IsNumeric(s) {
return gtime.NewFromTimeStamp(Int64(s))
} else {
t, _ := gtime.StrToTime(s)