refactor(encoding/gjson): change data parameter from type any to []byte (#3542)

This commit is contained in:
John Guo 2024-09-28 18:10:00 +08:00 committed by GitHub
parent cf742233e8
commit 9589384b36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 482 additions and 394 deletions

View File

@ -180,6 +180,9 @@ linters-settings:
# https://golangci-lint.run/usage/linters/#govet # https://golangci-lint.run/usage/linters/#govet
govet: govet:
# Report about shadowed variables.
# Default: false
# check-shadowing: true
# Settings per analyzer. # Settings per analyzer.
settings: settings:
# Analyzer name, run `go tool vet help` to see all analyzers. # Analyzer name, run `go tool vet help` to see all analyzers.

View File

@ -13,6 +13,7 @@ import (
"github.com/apolloconfig/agollo/v4" "github.com/apolloconfig/agollo/v4"
apolloConfig "github.com/apolloconfig/agollo/v4/env/config" apolloConfig "github.com/apolloconfig/agollo/v4/env/config"
"github.com/apolloconfig/agollo/v4/storage" "github.com/apolloconfig/agollo/v4/storage"
"github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"

View File

@ -138,7 +138,7 @@ func (c *Client) doUpdate(ctx context.Context, namespace string) (err error) {
) )
} }
var j *gjson.Json var j *gjson.Json
if j, err = gjson.LoadContent(cm.Data[c.config.DataItem]); err != nil { if j, err = gjson.LoadContent([]byte(cm.Data[c.config.DataItem])); err != nil {
return gerror.Wrapf( return gerror.Wrapf(
err, err,
`parse config map item from %s[%s] failed`, c.config.ConfigMap, c.config.DataItem, `parse config map item from %s[%s] failed`, c.config.ConfigMap, c.config.DataItem,

View File

@ -114,7 +114,7 @@ func (c *Client) updateLocalValue() (err error) {
func (c *Client) doUpdate(content string) (err error) { func (c *Client) doUpdate(content string) (err error) {
var j *gjson.Json var j *gjson.Json
if j, err = gjson.LoadContent(content); err != nil { if j, err = gjson.LoadContent([]byte(content)); err != nil {
return gerror.Wrap(err, `parse config map item from nacos failed`) return gerror.Wrap(err, `parse config map item from nacos failed`)
} }
c.value.Set(j) c.value.Set(j)

View File

@ -147,7 +147,7 @@ func (c *Client) doUpdate(ctx context.Context) (err error) {
return gerror.New("config file is empty") return gerror.New("config file is empty")
} }
var j *gjson.Json var j *gjson.Json
if j, err = gjson.LoadContent(c.client.GetContent()); err != nil { if j, err = gjson.LoadContent([]byte(c.client.GetContent())); err != nil {
return gerror.Wrap(err, `parse config map item from polaris failed`) return gerror.Wrap(err, `parse config map item from polaris failed`)
} }
c.value.Set(j) c.value.Set(j)

View File

@ -794,7 +794,7 @@ func Test_DB_ToJson(t *testing.T) {
} }
// ToJson // ToJson
resultJson, err := gjson.LoadContent(result.Json()) resultJson, err := gjson.LoadContent([]byte(result.Json()))
if err != nil { if err != nil {
gtest.Fatal(err) gtest.Fatal(err)
} }

View File

@ -894,7 +894,7 @@ func Test_DB_ToJson(t *testing.T) {
} }
// ToJson // ToJson
resultJson, err := gjson.LoadContent(result.Json()) resultJson, err := gjson.LoadContent([]byte(result.Json()))
if err != nil { if err != nil {
gtest.Fatal(err) gtest.Fatal(err)
} }

View File

@ -831,7 +831,7 @@ func Test_DB_ToJson(t *testing.T) {
} }
// ToJson // ToJson
resultJson, err := gjson.LoadContent(result.Json()) resultJson, err := gjson.LoadContent([]byte(result.Json()))
if err != nil { if err != nil {
gtest.Fatal(err) gtest.Fatal(err)
} }

View File

@ -831,7 +831,7 @@ func Test_DB_ToJson(t *testing.T) {
} }
// ToJson // ToJson
resultJson, err := gjson.LoadContent(result.Json()) resultJson, err := gjson.LoadContent([]byte(result.Json()))
if err != nil { if err != nil {
gtest.Fatal(err) gtest.Fatal(err)
} }

View File

@ -7,22 +7,10 @@
package gjson package gjson
import ( import (
"bytes"
"reflect" "reflect"
"github.com/gogf/gf/v2/encoding/gini"
"github.com/gogf/gf/v2/encoding/gproperties"
"github.com/gogf/gf/v2/encoding/gtoml"
"github.com/gogf/gf/v2/encoding/gxml"
"github.com/gogf/gf/v2/encoding/gyaml"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/reflection"
"github.com/gogf/gf/v2/internal/rwmutex" "github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
) )
@ -57,16 +45,26 @@ func NewWithTag(data interface{}, tags string, safe ...bool) *Json {
// or slice for data access reason, or it will make no sense. // or slice for data access reason, or it will make no sense.
func NewWithOptions(data interface{}, options Options) *Json { func NewWithOptions(data interface{}, options Options) *Json {
var j *Json var j *Json
switch data.(type) { switch result := data.(type) {
case string, []byte: case []byte:
if r, err := loadContentWithOptions(data, options); err == nil { if r, err := loadContentWithOptions(result, options); err == nil {
j = r j = r
} else { break
j = &Json{ }
p: &data, j = &Json{
c: byte(defaultSplitChar), p: &data,
vc: false, c: byte(defaultSplitChar),
} vc: false,
}
case string:
if r, err := loadContentWithOptions([]byte(result), options); err == nil {
j = r
break
}
j = &Json{
p: &data,
c: byte(defaultSplitChar),
vc: false,
} }
default: default:
var ( var (
@ -98,266 +96,3 @@ func NewWithOptions(data interface{}, options Options) *Json {
j.mu = rwmutex.Create(options.Safe) j.mu = rwmutex.Create(options.Safe)
return j return j
} }
// Load loads content from specified file `path`, and creates a Json object from its content.
func Load(path string, safe ...bool) (*Json, error) {
if p, err := gfile.Search(path); err != nil {
return nil, err
} else {
path = p
}
options := Options{
Type: ContentType(gfile.Ext(path)),
}
if len(safe) > 0 && safe[0] {
options.Safe = true
}
return doLoadContentWithOptions(gfile.GetBytesWithCache(path), options)
}
// LoadWithOptions creates a Json object from given JSON format content and options.
func LoadWithOptions(data interface{}, options Options) (*Json, error) {
return doLoadContentWithOptions(gconv.Bytes(data), options)
}
// LoadJson creates a Json object from given JSON format content.
func LoadJson(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeJson,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(gconv.Bytes(data), option)
}
// LoadXml creates a Json object from given XML format content.
func LoadXml(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeXml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(gconv.Bytes(data), option)
}
// LoadIni creates a Json object from given INI format content.
func LoadIni(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeIni,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(gconv.Bytes(data), option)
}
// LoadYaml creates a Json object from given YAML format content.
func LoadYaml(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeYaml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(gconv.Bytes(data), option)
}
// LoadToml creates a Json object from given TOML format content.
func LoadToml(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeToml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(gconv.Bytes(data), option)
}
// LoadProperties creates a Json object from given TOML format content.
func LoadProperties(data interface{}, safe ...bool) (*Json, error) {
option := Options{
Type: ContentTypeProperties,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return doLoadContentWithOptions(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 ContentType, 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:]
}
options := Options{
Type: dataType,
StrNumber: true,
}
if len(safe) > 0 && safe[0] {
options.Safe = true
}
return doLoadContentWithOptions(content, options)
}
// IsValidDataType checks and returns whether given `dataType` a valid data type for loading.
func IsValidDataType(dataType ContentType) bool {
if dataType == "" {
return false
}
if dataType[0] == '.' {
dataType = dataType[1:]
}
switch dataType {
case
ContentTypeJson,
ContentTypeJs,
ContentTypeXml,
ContentTypeYaml,
ContentTypeYml,
ContentTypeToml,
ContentTypeIni,
ContentTypeProperties:
return true
}
return false
}
func loadContentWithOptions(data interface{}, options Options) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return NewWithOptions(nil, options), nil
}
if options.Type == "" {
options.Type = checkDataType(content)
}
return loadContentTypeWithOptions(content, options)
}
func loadContentTypeWithOptions(data interface{}, options Options) (*Json, error) {
content := gconv.Bytes(data)
if len(content) == 0 {
return NewWithOptions(nil, options), nil
}
// ignore UTF8-BOM
if content[0] == 0xEF && content[1] == 0xBB && content[2] == 0xBF {
content = content[3:]
}
return doLoadContentWithOptions(content, options)
}
// doLoadContent creates a Json object from given content.
// It supports data content type as follows:
// JSON, XML, INI, YAML and TOML.
func doLoadContentWithOptions(data []byte, options Options) (*Json, error) {
var (
err error
result interface{}
)
if len(data) == 0 {
return NewWithOptions(nil, options), nil
}
if options.Type == "" {
options.Type = checkDataType(data)
}
options.Type = ContentType(gstr.TrimLeft(
string(options.Type), "."),
)
switch options.Type {
case ContentTypeJson, ContentTypeJs:
case ContentTypeXml:
if data, err = gxml.ToJson(data); err != nil {
return nil, err
}
case ContentTypeYaml, ContentTypeYml:
if data, err = gyaml.ToJson(data); err != nil {
return nil, err
}
case ContentTypeToml:
if data, err = gtoml.ToJson(data); err != nil {
return nil, err
}
case ContentTypeIni:
if data, err = gini.ToJson(data); err != nil {
return nil, err
}
case ContentTypeProperties:
if data, err = gproperties.ToJson(data); err != nil {
return nil, err
}
default:
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`unsupported type "%s" for loading`,
options.Type,
)
}
if err != nil {
return nil, err
}
decoder := json.NewDecoder(bytes.NewReader(data))
if options.StrNumber {
decoder.UseNumber()
}
if err = decoder.Decode(&result); err != nil {
return nil, err
}
switch result.(type) {
case string, []byte:
return nil, gerror.Newf(`json decoding failed for content: %s`, data)
}
return NewWithOptions(result, options), nil
}
// checkDataType automatically checks and returns the data type for `content`.
// Note that it uses regular expression for loose checking, you can use LoadXXX/LoadContentType
// functions to load the content for certain content type.
func checkDataType(content []byte) ContentType {
if json.Valid(content) {
return ContentTypeJson
} else if gregex.IsMatch(`^<.+>[\S\s]+<.+>\s*$`, content) {
return ContentTypeXml
} else if !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*"""[\s\S]+"""`, content) &&
!gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*'''[\s\S]+'''`, content) &&
((gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*".+"`, content) || gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*\w+`, content)) ||
(gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*".+"`, content) || gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, content))) {
return ContentTypeYaml
} else if !gregex.IsMatch(`^[\s\t\n\r]*;.+`, content) &&
!gregex.IsMatch(`[\s\t\n\r]+;.+`, content) &&
!gregex.IsMatch(`[\n\r]+[\s\t\w\-]+\.[\s\t\w\-]+\s*=\s*.+`, content) &&
(gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, content) || gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content)) {
return ContentTypeToml
} else if gregex.IsMatch(`\[[\w\.]+\]`, content) &&
(gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, content) || gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content)) {
// Must contain "[xxx]" section.
return ContentTypeIni
} else if gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, content) {
return ContentTypeProperties
} else {
return ""
}
}

View File

@ -0,0 +1,279 @@
// 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 gjson
import (
"bytes"
"github.com/gogf/gf/v2/encoding/gini"
"github.com/gogf/gf/v2/encoding/gproperties"
"github.com/gogf/gf/v2/encoding/gtoml"
"github.com/gogf/gf/v2/encoding/gxml"
"github.com/gogf/gf/v2/encoding/gyaml"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
// LoadWithOptions creates a Json object from given JSON format content and options.
func LoadWithOptions(data []byte, options Options) (*Json, error) {
return loadContentWithOptions(data, options)
}
// LoadJson creates a Json object from given JSON format content.
func LoadJson(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeJson,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(data, option)
}
// LoadXml creates a Json object from given XML format content.
func LoadXml(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeXml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(data, option)
}
// LoadIni creates a Json object from given INI format content.
func LoadIni(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeIni,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(data, option)
}
// LoadYaml creates a Json object from given YAML format content.
func LoadYaml(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeYaml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(data, option)
}
// LoadToml creates a Json object from given TOML format content.
func LoadToml(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeToml,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(data, option)
}
// LoadProperties creates a Json object from given TOML format content.
func LoadProperties(data []byte, safe ...bool) (*Json, error) {
var option = Options{
Type: ContentTypeProperties,
}
if len(safe) > 0 && safe[0] {
option.Safe = true
}
return loadContentWithOptions(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 []byte, safe ...bool) (*Json, error) {
return LoadContentType("", data, 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 ContentType, data []byte, safe ...bool) (*Json, error) {
if len(data) == 0 {
return New(nil, safe...), nil
}
var options = Options{
Type: dataType,
StrNumber: true,
}
if len(safe) > 0 && safe[0] {
options.Safe = true
}
return loadContentWithOptions(data, options)
}
// IsValidDataType checks and returns whether given `dataType` a valid data type for loading.
func IsValidDataType(dataType ContentType) bool {
if dataType == "" {
return false
}
if dataType[0] == '.' {
dataType = dataType[1:]
}
switch dataType {
case
ContentTypeJson,
ContentTypeJs,
ContentTypeXml,
ContentTypeYaml,
ContentTypeYml,
ContentTypeToml,
ContentTypeIni,
ContentTypeProperties:
return true
}
return false
}
func trimBOM(data []byte) []byte {
if len(data) < 3 {
return data
}
if data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF {
data = data[3:]
}
return data
}
// loadContentWithOptions creates a Json object from given content.
// It supports data content type as follows:
// JSON, XML, INI, YAML and TOML.
func loadContentWithOptions(data []byte, options Options) (*Json, error) {
var (
err error
result interface{}
)
data = trimBOM(data)
if len(data) == 0 {
return NewWithOptions(nil, options), nil
}
if options.Type == "" {
options.Type, err = checkDataType(data)
if err != nil {
return nil, err
}
}
options.Type = ContentType(gstr.TrimLeft(
string(options.Type), "."),
)
switch options.Type {
case ContentTypeJson, ContentTypeJs:
case ContentTypeXml:
data, err = gxml.ToJson(data)
case ContentTypeYaml, ContentTypeYml:
data, err = gyaml.ToJson(data)
case ContentTypeToml:
data, err = gtoml.ToJson(data)
case ContentTypeIni:
data, err = gini.ToJson(data)
case ContentTypeProperties:
data, err = gproperties.ToJson(data)
default:
err = gerror.NewCodef(
gcode.CodeInvalidParameter,
`unsupported type "%s" for loading`,
options.Type,
)
}
if err != nil {
return nil, err
}
decoder := json.NewDecoder(bytes.NewReader(data))
if options.StrNumber {
decoder.UseNumber()
}
if err = decoder.Decode(&result); err != nil {
return nil, err
}
switch result.(type) {
case string, []byte:
return nil, gerror.Newf(`json decoding failed for content: %s`, data)
}
return NewWithOptions(result, options), nil
}
// checkDataType automatically checks and returns the data type for `content`.
// Note that it uses regular expression for loose checking, you can use LoadXXX/LoadContentType
// functions to load the content for certain content type.
// TODO it is not graceful here automatic judging the data type.
// TODO it might be removed in the future, which lets the user explicitly specify the data type not automatic checking.
func checkDataType(data []byte) (ContentType, error) {
switch {
case json.Valid(data):
return ContentTypeJson, nil
case isXmlContent(data):
return ContentTypeXml, nil
case isYamlContent(data):
return ContentTypeYaml, nil
case isTomlContent(data):
return ContentTypeToml, nil
case isIniContent(data):
// Must contain "[xxx]" section.
return ContentTypeIni, nil
case isPropertyContent(data):
return ContentTypeProperties, nil
default:
return "", gerror.NewCode(
gcode.CodeOperationFailed,
`unable auto check the data format type`,
)
}
}
func isXmlContent(data []byte) bool {
return gregex.IsMatch(`^\s*<.+>[\S\s]+<.+>\s*$`, data)
}
func isYamlContent(data []byte) bool {
return !gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*"""[\s\S]+"""`, data) &&
!gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*'''[\s\S]+'''`, data) &&
((gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*".+"`, data) ||
gregex.IsMatch(`^[\n\r]*[\w\-\s\t]+\s*:\s*\w+`, data)) ||
(gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*".+"`, data) ||
gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, data)))
}
func isTomlContent(data []byte) bool {
return !gregex.IsMatch(`^[\s\t\n\r]*;.+`, data) &&
!gregex.IsMatch(`[\s\t\n\r]+;.+`, data) &&
!gregex.IsMatch(`[\n\r]+[\s\t\w\-]+\.[\s\t\w\-]+\s*=\s*.+`, data) &&
(gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, data) ||
gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data))
}
func isIniContent(data []byte) bool {
return gregex.IsMatch(`\[[\w\.]+\]`, data) &&
(gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*".+"`, data) ||
gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data))
}
func isPropertyContent(data []byte) bool {
return gregex.IsMatch(`[\n\r]*[\s\t\w\-\."]+\s*=\s*\w+`, data)
}

View File

@ -0,0 +1,34 @@
// 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 gjson
import "github.com/gogf/gf/v2/os/gfile"
// Load loads content from specified file `path`, and creates a Json object from its content.
// Deprecated: use LoadPath instead.
func Load(path string, safe ...bool) (*Json, error) {
var isSafe bool
if len(safe) > 0 {
isSafe = safe[0]
}
return LoadPath(path, Options{
Safe: isSafe,
})
}
// LoadPath loads content from specified file `path`, and creates a Json object from its content.
func LoadPath(path string, options Options) (*Json, error) {
if p, err := gfile.Search(path); err != nil {
return nil, err
} else {
path = p
}
if options.Type == "" {
options.Type = ContentType(gfile.Ext(path))
}
return loadContentWithOptions(gfile.GetBytesWithCache(path), options)
}

View File

@ -29,7 +29,7 @@ func ExampleLoad() {
} }
func ExampleLoadJson() { func ExampleLoadJson() {
jsonContent := `{"name":"john", "score":"100"}` jsonContent := []byte(`{"name":"john", "score":"100"}`)
j, _ := gjson.LoadJson(jsonContent) j, _ := gjson.LoadJson(jsonContent)
fmt.Println(j.Get("name")) fmt.Println(j.Get("name"))
fmt.Println(j.Get("score")) fmt.Println(j.Get("score"))
@ -40,11 +40,13 @@ func ExampleLoadJson() {
} }
func ExampleLoadXml() { func ExampleLoadXml() {
xmlContent := `<?xml version="1.0" encoding="UTF-8"?> xmlContent := []byte(`
<base> <?xml version="1.0" encoding="UTF-8"?>
<name>john</name> <base>
<score>100</score> <name>john</name>
</base>` <score>100</score>
</base>
`)
j, _ := gjson.LoadXml(xmlContent) j, _ := gjson.LoadXml(xmlContent)
fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.name"))
fmt.Println(j.Get("base.score")) fmt.Println(j.Get("base.score"))
@ -55,11 +57,11 @@ func ExampleLoadXml() {
} }
func ExampleLoadIni() { func ExampleLoadIni() {
iniContent := ` iniContent := []byte(`
[base] [base]
name = john name = john
score = 100 score = 100
` `)
j, _ := gjson.LoadIni(iniContent) j, _ := gjson.LoadIni(iniContent)
fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.name"))
fmt.Println(j.Get("base.score")) fmt.Println(j.Get("base.score"))
@ -70,10 +72,11 @@ func ExampleLoadIni() {
} }
func ExampleLoadYaml() { func ExampleLoadYaml() {
yamlContent := yamlContent := []byte(`
`base: base:
name: john name: john
score: 100` score: 100
`)
j, _ := gjson.LoadYaml(yamlContent) j, _ := gjson.LoadYaml(yamlContent)
fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.name"))
@ -85,10 +88,11 @@ func ExampleLoadYaml() {
} }
func ExampleLoadToml() { func ExampleLoadToml() {
tomlContent := tomlContent := []byte(`
`[base] [base]
name = "john" name = "john"
score = 100` score = 100
`)
j, _ := gjson.LoadToml(tomlContent) j, _ := gjson.LoadToml(tomlContent)
fmt.Println(j.Get("base.name")) fmt.Println(j.Get("base.name"))
@ -100,7 +104,7 @@ func ExampleLoadToml() {
} }
func ExampleLoadContent() { func ExampleLoadContent() {
jsonContent := `{"name":"john", "score":"100"}` jsonContent := []byte(`{"name":"john", "score":"100"}`)
j, _ := gjson.LoadContent(jsonContent) j, _ := gjson.LoadContent(jsonContent)
@ -132,11 +136,13 @@ func ExampleLoadContent_UTF8BOM() {
} }
func ExampleLoadContent_Xml() { func ExampleLoadContent_Xml() {
xmlContent := `<?xml version="1.0" encoding="UTF-8"?> xmlContent := []byte(`
<base> <?xml version="1.0" encoding="UTF-8"?>
<name>john</name> <base>
<score>100</score> <name>john</name>
</base>` <score>100</score>
</base>
`)
x, _ := gjson.LoadContent(xmlContent) x, _ := gjson.LoadContent(xmlContent)
@ -149,16 +155,20 @@ func ExampleLoadContent_Xml() {
} }
func ExampleLoadContentType() { func ExampleLoadContentType() {
jsonContent := `{"name":"john", "score":"100"}` var (
xmlContent := `<?xml version="1.0" encoding="UTF-8"?> jsonContent = []byte(`{"name":"john", "score":"100"}`)
<base> xmlContent = []byte(`
<name>john</name> <?xml version="1.0" encoding="UTF-8"?>
<score>100</score> <base>
</base>` <name>john</name>
<score>100</score>
</base>
`)
)
j, _ := gjson.LoadContentType("json", jsonContent) j, _ := gjson.LoadContentType("json", jsonContent)
x, _ := gjson.LoadContentType("xml", xmlContent) x, _ := gjson.LoadContentType("xml", xmlContent)
j1, _ := gjson.LoadContentType("json", "") j1, _ := gjson.LoadContentType("json", []byte(""))
fmt.Println(j.Get("name")) fmt.Println(j.Get("name"))
fmt.Println(j.Get("score")) fmt.Println(j.Get("score"))

View File

@ -51,7 +51,7 @@ func ExampleDecodeToJson_PatternViolenceCheck() {
} }
func ExampleJson_Get_MapSliceChange() { func ExampleJson_Get_MapSliceChange() {
jsonContent := `{"map":{"key":"value"}, "slice":[59,90]}` jsonContent := []byte(`{"map":{"key":"value"}, "slice":[59,90]}`)
j, _ := gjson.LoadJson(jsonContent) j, _ := gjson.LoadJson(jsonContent)
m := j.Get("map").Map() m := j.Get("map").Map()
fmt.Println(m) fmt.Println(m)

View File

@ -871,13 +871,14 @@ func ExampleJson_IsNil() {
} }
func ExampleJson_Get() { func ExampleJson_Get() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : ["John", "Ming"] "array" : ["John", "Ming"]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
fmt.Println(j.Get(".")) fmt.Println(j.Get("."))
@ -896,13 +897,14 @@ func ExampleJson_Get() {
} }
func ExampleJson_GetJson() { func ExampleJson_GetJson() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : ["John", "Ming"] "array" : ["John", "Ming"]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -913,13 +915,14 @@ func ExampleJson_GetJson() {
} }
func ExampleJson_GetJsons() { func ExampleJson_GetJsons() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 3, "count" : 3,
"array" : [{"Age":18,"Name":"John"}, {"Age":20,"Name":"Tom"}] "array" : [{"Age":18,"Name":"John"}, {"Age":20,"Name":"Tom"}]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -934,16 +937,17 @@ func ExampleJson_GetJsons() {
} }
func ExampleJson_GetJsonMap() { func ExampleJson_GetJsonMap() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : { "array" : {
"info" : {"Age":18,"Name":"John"}, "info" : {"Age":18,"Name":"John"},
"addr" : {"City":"Chengdu","Company":"Tencent"} "addr" : {"City":"Chengdu","Company":"Tencent"}
} }
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1056,9 +1060,9 @@ func ExampleJson_Contains() {
} }
func ExampleJson_Len() { func ExampleJson_Len() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"nameArray" : ["Join", "Tom"], "nameArray" : ["Join", "Tom"],
"infoMap" : { "infoMap" : {
@ -1067,7 +1071,8 @@ func ExampleJson_Len() {
"addr" : "ChengDu" "addr" : "ChengDu"
} }
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1080,13 +1085,14 @@ func ExampleJson_Len() {
} }
func ExampleJson_Append() { func ExampleJson_Append() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : ["John", "Ming"] "array" : ["John", "Ming"]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1099,13 +1105,14 @@ func ExampleJson_Append() {
} }
func ExampleJson_MustAppend() { func ExampleJson_MustAppend() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : ["John", "Ming"] "array" : ["John", "Ming"]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1118,9 +1125,9 @@ func ExampleJson_MustAppend() {
} }
func ExampleJson_Map() { func ExampleJson_Map() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"info" : { "info" : {
"name" : "John", "name" : "John",
@ -1128,7 +1135,8 @@ func ExampleJson_Map() {
"addr" : "ChengDu" "addr" : "ChengDu"
} }
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1139,13 +1147,14 @@ func ExampleJson_Map() {
} }
func ExampleJson_Array() { func ExampleJson_Array() {
data := data := []byte(`
`{ {
"users" : { "users" : {
"count" : 1, "count" : 1,
"array" : ["John", "Ming"] "array" : ["John", "Ming"]
} }
}` }
`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
@ -1156,7 +1165,7 @@ func ExampleJson_Array() {
} }
func ExampleJson_Scan() { func ExampleJson_Scan() {
data := `{"name":"john","age":"18"}` data := []byte(`{"name":"john","age":"18"}`)
type BaseInfo struct { type BaseInfo struct {
Name string Name string
@ -1175,7 +1184,7 @@ func ExampleJson_Scan() {
} }
func ExampleJson_Dump() { func ExampleJson_Dump() {
data := `{"name":"john","age":"18"}` data := []byte(`{"name":"john","age":"18"}`)
j, _ := gjson.LoadContent(data) j, _ := gjson.LoadContent(data)
j.Dump() j.Dump()

View File

@ -49,11 +49,11 @@ func Test_ToJson(t *testing.T) {
} }
func Test_MapAttributeConvert(t *testing.T) { func Test_MapAttributeConvert(t *testing.T) {
var data = ` var data = []byte(`
{ {
"title": {"l1":"标签1","l2":"标签2"} "title": {"l1":"标签1","l2":"标签2"}
} }
` `)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
j, err := gjson.LoadContent(data) j, err := gjson.LoadContent(data)
gtest.AssertNil(err) gtest.AssertNil(err)

View File

@ -105,7 +105,8 @@ func Test_Load_XML(t *testing.T) {
// XML // XML
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
xml := `<?xml version="1.0"?> xml := []byte(`
<?xml version="1.0"?>
<Output type="o"> <Output type="o">
<itotalSize>0</itotalSize> <itotalSize>0</itotalSize>
@ -114,7 +115,8 @@ func Test_Load_XML(t *testing.T) {
<itotalRecords>GF框架</itotalRecords> <itotalRecords>GF框架</itotalRecords>
<nworkOrderDtos/> <nworkOrderDtos/>
<nworkOrderFrontXML/> <nworkOrderFrontXML/>
</Output>` </Output>
`)
j, err := gjson.LoadContent(xml) j, err := gjson.LoadContent(xml)
t.AssertNil(err) t.AssertNil(err)
t.Assert(j.Get("Output.ipageIndex"), "2") t.Assert(j.Get("Output.ipageIndex"), "2")
@ -250,10 +252,10 @@ func Test_Load_Basic(t *testing.T) {
t.AssertNil(err) t.AssertNil(err)
t.Assert(j.Interface(), nil) t.Assert(j.Interface(), nil)
j, err = gjson.LoadContent(`{"name": "gf"}`) j, err = gjson.LoadContent([]byte(`{"name": "gf"}`))
t.AssertNil(err) t.AssertNil(err)
j, err = gjson.LoadContent(`{"name": "gf"""}`) j, err = gjson.LoadContent([]byte(`{"name": "gf"""}`))
t.AssertNE(err, nil) t.AssertNE(err, nil)
j = gjson.New(&g.Map{"name": "gf"}) j = gjson.New(&g.Map{"name": "gf"})
@ -263,7 +265,7 @@ func Test_Load_Basic(t *testing.T) {
} }
func Test_Load_Ini(t *testing.T) { func Test_Load_Ini(t *testing.T) {
var data = ` var data = []byte(`
;注释 ;注释
@ -277,7 +279,7 @@ enable=true
user=root user=root
password=password password=password
` `)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
j, err := gjson.LoadContent(data) j, err := gjson.LoadContent(data)
@ -320,7 +322,7 @@ enable=true
} }
func Test_Load_YamlWithV3(t *testing.T) { func Test_Load_YamlWithV3(t *testing.T) {
content := ` content := []byte(`
# CLI tool, only in development environment. # CLI tool, only in development environment.
# https://goframe.org/pages/viewpage.action?pageId=3673173 # https://goframe.org/pages/viewpage.action?pageId=3673173
gfcli: gfcli:
@ -355,7 +357,7 @@ gfcli:
noModelComment : true noModelComment : true
overwriteDao : true overwriteDao : true
modelFileForDao : "model_dao.go" modelFileForDao : "model_dao.go"
` `)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
_, err := gjson.LoadContent(content) _, err := gjson.LoadContent(content)
t.AssertNil(err) t.AssertNil(err)
@ -363,7 +365,7 @@ gfcli:
} }
func Test_Load_Properties(t *testing.T) { func Test_Load_Properties(t *testing.T) {
var data = ` var data = []byte(`
#注释 #注释
@ -375,7 +377,7 @@ DBINFO.type=mysql
DBINFO.user=root DBINFO.user=root
DBINFO.password=password DBINFO.password=password
` `)
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
j, err := gjson.LoadContent(data) j, err := gjson.LoadContent(data)

View File

@ -138,7 +138,7 @@ func Test_Struct1(t *testing.T) {
type UserCollectionAddReq struct { type UserCollectionAddReq struct {
BaseInfo []BaseInfoItem `db:"_" json:"baseInfo" field:"_"` BaseInfo []BaseInfoItem `db:"_" json:"baseInfo" field:"_"`
} }
jsonContent := `{ jsonContent := []byte(`{
"baseInfo": [{ "baseInfo": [{
"idCardNumber": "520101199412141111", "idCardNumber": "520101199412141111",
"isHouseholder": true, "isHouseholder": true,
@ -195,7 +195,8 @@ func Test_Struct1(t *testing.T) {
"incomeInfo": [], "incomeInfo": [],
"liabilityInfo": [] "liabilityInfo": []
}] }]
}` }
`)
data := new(UserCollectionAddReq) data := new(UserCollectionAddReq)
j, err := gjson.LoadJson(jsonContent, true) j, err := gjson.LoadJson(jsonContent, true)
t.AssertNil(err) t.AssertNil(err)
@ -218,12 +219,14 @@ func Test_Struct(t *testing.T) {
Items []*Item `json:"items"` Items []*Item `json:"items"`
} }
txt := `{ txt := []byte(`
"id":"88888", {
"me":{"name":"mikey","day":"20009"}, "id":"88888",
"txt":"hello", "me":{"name":"mikey","day":"20009"},
"items":null "txt":"hello",
}` "items":null
}
`)
j, err := gjson.LoadContent(txt) j, err := gjson.LoadContent(txt)
t.AssertNil(err) t.AssertNil(err)
@ -281,13 +284,15 @@ func Test_Struct_Complicated(t *testing.T) {
} }
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
jsonContent := `{ jsonContent := []byte(`
{
"certList":[ "certList":[
{"certId":"2023313","certInfo":"{\"address\":\"xxxxxxx\",\"phoneNumber\":\"15084890\",\"companyName\":\"dddd\",\"communityCreditCode\":\"91110111MBE1G2B\",\"operateRange\":\"fff\",\"registerNo\":\"91110111MA00G2B\",\"legalPersonName\":\"rrr\"}","srcType":"1","statusCode":"2"}, {"certId":"2023313","certInfo":"{\"address\":\"xxxxxxx\",\"phoneNumber\":\"15084890\",\"companyName\":\"dddd\",\"communityCreditCode\":\"91110111MBE1G2B\",\"operateRange\":\"fff\",\"registerNo\":\"91110111MA00G2B\",\"legalPersonName\":\"rrr\"}","srcType":"1","statusCode":"2"},
{"certId":"2023314","certInfo":"{\"identNo\":\"342224196507051\",\"userRealname\":\"xxxx\",\"identType\":\"01\"}","srcType":"8","statusCode":"0"}, {"certId":"2023314","certInfo":"{\"identNo\":\"342224196507051\",\"userRealname\":\"xxxx\",\"identType\":\"01\"}","srcType":"8","statusCode":"0"},
{"certId":"2023322","certInfo":"{\"businessLicense\":\"91110111MA00BE1G\",\"companyName\":\"sssss\",\"communityCreditCode\":\"91110111MA00BE1\"}","srcType":"2","statusCode":"0"} {"certId":"2023322","certInfo":"{\"businessLicense\":\"91110111MA00BE1G\",\"companyName\":\"sssss\",\"communityCreditCode\":\"91110111MA00BE1\"}","srcType":"2","statusCode":"0"}
] ]
}` }
`)
j, err := gjson.LoadContent(jsonContent) j, err := gjson.LoadContent(jsonContent)
t.AssertNil(err) t.AssertNil(err)
var response = new(Response) var response = new(Response)

View File

@ -18,7 +18,9 @@ func Test_checkDataType(t *testing.T) {
bb = """ bb = """
dig := dig; END;""" dig := dig; END;"""
`) `)
t.Assert(checkDataType(data), "toml") dataType, err := checkDataType(data)
t.AssertNil(err)
t.Assert(dataType, "toml")
}) })
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
@ -32,7 +34,9 @@ dd = 11
disk = "127.0.0.1:6379,0" disk = "127.0.0.1:6379,0"
cache = "127.0.0.1:6379,1" cache = "127.0.0.1:6379,1"
`) `)
t.Assert(checkDataType(data), "toml") dataType, err := checkDataType(data)
t.AssertNil(err)
t.Assert(dataType, "toml")
}) })
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
@ -86,7 +90,9 @@ dd = 11
// fmt.Println(gregex.IsMatch(`[\s\t\n\r]+[\w\-]+\s*:\s*".+"`, data)) // fmt.Println(gregex.IsMatch(`[\s\t\n\r]+[\w\-]+\s*:\s*".+"`, data))
// fmt.Println(gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, data)) // fmt.Println(gregex.IsMatch(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, data))
// fmt.Println(gregex.MatchString(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, string(data))) // fmt.Println(gregex.MatchString(`[\n\r]+[\w\-\s\t]+\s*:\s*\w+`, string(data)))
t.Assert(checkDataType(data), "toml") dataType, err := checkDataType(data)
t.AssertNil(err)
t.Assert(dataType, "toml")
}) })
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
@ -111,7 +117,9 @@ k8s-inner-api = http://127.0.0.1:8081/kube/add
conf_dir = ./config conf_dir = ./config
app_conf = ./config/app.ini app_conf = ./config/app.ini
`) `)
t.Assert(checkDataType(data), "ini") dataType, err := checkDataType(data)
t.AssertNil(err)
t.Assert(dataType, "ini")
}) })
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
@ -129,6 +137,8 @@ wget http://consul.infra:8500/v1/kv/app_{{.SwimlaneName}}/{{.RepoName}}/.env.qa?
npm run build:qa npm run build:qa
""" """
`) `)
t.Assert(checkDataType(data), "toml") dataType, err := checkDataType(data)
t.AssertNil(err)
t.Assert(dataType, "toml")
}) })
} }

View File

@ -37,7 +37,7 @@ func NewAdapterContent(content ...string) (*AdapterContent, error) {
// SetContent sets customized configuration content for specified `file`. // SetContent sets customized configuration content for specified `file`.
// The `file` is unnecessary param, default is DefaultConfigFile. // The `file` is unnecessary param, default is DefaultConfigFile.
func (a *AdapterContent) SetContent(content string) error { func (a *AdapterContent) SetContent(content string) error {
j, err := gjson.LoadContent(content, true) j, err := gjson.LoadContent([]byte(content), true)
if err != nil { if err != nil {
return gerror.Wrap(err, `load configuration content failed`) return gerror.Wrap(err, `load configuration content failed`)
} }

View File

@ -262,9 +262,9 @@ func (a *AdapterFile) getJson(fileNameOrPath ...string) (configJson *gjson.Json,
// Note that the underlying configuration json object operations are concurrent safe. // Note that the underlying configuration json object operations are concurrent safe.
dataType := gjson.ContentType(gfile.ExtName(filePath)) dataType := gjson.ContentType(gfile.ExtName(filePath))
if gjson.IsValidDataType(dataType) && !isFromConfigContent { if gjson.IsValidDataType(dataType) && !isFromConfigContent {
configJson, err = gjson.LoadContentType(dataType, content, true) configJson, err = gjson.LoadContentType(dataType, []byte(content), true)
} else { } else {
configJson, err = gjson.LoadContent(content, true) configJson, err = gjson.LoadContent([]byte(content), true)
} }
if err != nil { if err != nil {
if filePath != "" { if filePath != "" {