mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
gjson模块支持内容修改特性,开发中
This commit is contained in:
@ -21,13 +21,9 @@ import (
|
||||
|
||||
// json解析结果存放数组
|
||||
type Json struct {
|
||||
// 注意这是一个指针
|
||||
value *interface{}
|
||||
p *interface{} // 注意这是一个指针
|
||||
}
|
||||
|
||||
// 一个json变量
|
||||
type JsonVar interface{}
|
||||
|
||||
// 编码go变量为json字符串,并返回json字符串指针
|
||||
func Encode (v interface{}) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
@ -106,8 +102,8 @@ func NewJson(v *interface{}) *Json {
|
||||
|
||||
// 将指定的json内容转换为指定结构返回,查找失败或者转换失败,目标对象转换为nil
|
||||
// 注意第二个参数需要给的是变量地址
|
||||
func (p *Json) GetToVar(pattern string, v interface{}) error {
|
||||
r := p.Get(pattern)
|
||||
func (j *Json) GetToVar(pattern string, v interface{}) error {
|
||||
r := j.Get(pattern)
|
||||
if r != nil {
|
||||
if t, err := Encode(r); err == nil {
|
||||
return DecodeTo(t, v)
|
||||
@ -122,8 +118,8 @@ func (p *Json) GetToVar(pattern string, v interface{}) error {
|
||||
|
||||
// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
func (p *Json) GetMap(pattern string) map[string]interface{} {
|
||||
result := p.Get(pattern)
|
||||
func (j *Json) GetMap(pattern string) map[string]interface{} {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(map[string]interface{}); ok {
|
||||
return r
|
||||
@ -133,8 +129,8 @@ func (p *Json) GetMap(pattern string) map[string]interface{} {
|
||||
}
|
||||
|
||||
// 将检索值转换为Json对象指针返回
|
||||
func (p *Json) GetJson(pattern string) *Json {
|
||||
result := p.Get(pattern)
|
||||
func (j *Json) GetJson(pattern string) *Json {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
return &Json{&result}
|
||||
}
|
||||
@ -143,8 +139,8 @@ func (p *Json) GetJson(pattern string) *Json {
|
||||
|
||||
// 获得一个数组[]interface{},方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
func (p *Json) GetArray(pattern string) []interface{} {
|
||||
result := p.Get(pattern)
|
||||
func (j *Json) GetArray(pattern string) []interface{} {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.([]interface{}); ok {
|
||||
return r
|
||||
@ -154,114 +150,208 @@ func (p *Json) GetArray(pattern string) []interface{} {
|
||||
}
|
||||
|
||||
// 返回指定json中的string
|
||||
func (p *Json) GetString(pattern string) string {
|
||||
return gconv.String(p.Get(pattern))
|
||||
func (j *Json) GetString(pattern string) string {
|
||||
return gconv.String(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 返回指定json中的bool(false:"", 0, false, off)
|
||||
func (p *Json) GetBool(pattern string) bool {
|
||||
return gconv.Bool(p.Get(pattern))
|
||||
func (j *Json) GetBool(pattern string) bool {
|
||||
return gconv.Bool(j.Get(pattern))
|
||||
}
|
||||
|
||||
func (p *Json) GetInt(pattern string) int {
|
||||
return gconv.Int(p.Get(pattern))
|
||||
func (j *Json) GetInt(pattern string) int {
|
||||
return gconv.Int(j.Get(pattern))
|
||||
}
|
||||
|
||||
func (p *Json) GetUint(pattern string) uint {
|
||||
return gconv.Uint(p.Get(pattern))
|
||||
func (j *Json) GetUint(pattern string) uint {
|
||||
return gconv.Uint(j.Get(pattern))
|
||||
}
|
||||
|
||||
func (p *Json) GetFloat32(pattern string) float32 {
|
||||
return gconv.Float32(p.Get(pattern))
|
||||
func (j *Json) GetFloat32(pattern string) float32 {
|
||||
return gconv.Float32(j.Get(pattern))
|
||||
}
|
||||
|
||||
func (p *Json) GetFloat64(pattern string) float64 {
|
||||
return gconv.Float64(p.Get(pattern))
|
||||
func (j *Json) GetFloat64(pattern string) float64 {
|
||||
return gconv.Float64(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 根据pattern查找并设置数据
|
||||
// 注意:写入的时候"."符号只能表示层级,不能使用带"."符号的键名
|
||||
func (j *Json) Set(pattern string, value interface{}) error {
|
||||
array := strings.Split(pattern, ".")
|
||||
// root节点
|
||||
if len(array) == 1 {
|
||||
return j.setRoot(pattern, value)
|
||||
}
|
||||
pointer := j.p
|
||||
length := len(array)
|
||||
for i:= 0; i < length; i++ {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if i == length - 1 {
|
||||
(*pointer).(map[string]interface{})[array[i]] = value
|
||||
} else {
|
||||
v, ok := (*pointer).(map[string]interface{})[array[i]]
|
||||
if !ok {
|
||||
if strings.Compare(array[i], "0") == 0 {
|
||||
v = make([]interface{}, 0)
|
||||
} else {
|
||||
v = make(map[string]interface{})
|
||||
}
|
||||
(*pointer).(map[string]interface{})[array[i]] = v
|
||||
}
|
||||
pointer = &v
|
||||
}
|
||||
case []interface{}:
|
||||
if isNumeric(array[i]) {
|
||||
if n, err := strconv.Atoi(array[i]); err == nil {
|
||||
if i == length - 1 {
|
||||
(*pointer).([]interface{})[n] = value
|
||||
if len((*pointer).([]interface{})) > n {
|
||||
(*pointer).([]interface{})[n] = value
|
||||
} else {
|
||||
// 注意这里产生了临时变量和赋值拷贝
|
||||
array := (*pointer).([]interface{})
|
||||
array = append(array, value)
|
||||
*pointer = array
|
||||
}
|
||||
break
|
||||
} else {
|
||||
pointer = &(*pointer).([]interface{})[n]
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 修改根节点数据
|
||||
func (j *Json) setRoot(pattern string, value interface{}) error {
|
||||
switch (*j.p).(type) {
|
||||
case map[string]interface{}:
|
||||
(*j.p).(map[string]interface{})[pattern] = value
|
||||
case []interface{}:
|
||||
if isNumeric(pattern) {
|
||||
if n, err := strconv.Atoi(pattern); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if len((*j.p).([]interface{})) > n {
|
||||
(*j.p).([]interface{})[n] = value
|
||||
} else {
|
||||
// 注意这里产生了临时变量和赋值拷贝
|
||||
array := (*j.p).([]interface{})
|
||||
array = append(array, value)
|
||||
*j.p = array
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据约定字符串方式访问json解析数据,参数形如: "items.name.first", "list.0"
|
||||
// 返回的结果类型的interface{},因此需要自己做类型转换
|
||||
// 如果找不到对应节点的数据,返回nil
|
||||
func (p *Json) Get(pattern string) interface{} {
|
||||
var result interface{}
|
||||
pointer := p.value
|
||||
array := strings.Split(pattern, ".")
|
||||
length := len(array)
|
||||
for i:= 0; i < length; i++ {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; ok {
|
||||
if i == length - 1 {
|
||||
result = v
|
||||
} else {
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case []interface{}:
|
||||
if isNumeric(array[i]) {
|
||||
n, err := strconv.Atoi(array[i])
|
||||
if err == nil && len((*pointer).([]interface{})) > n {
|
||||
if i == length - 1 {
|
||||
result = (*pointer).([]interface{})[n]
|
||||
break;
|
||||
} else {
|
||||
pointer = &(*pointer).([]interface{})[n]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
func (j *Json) Get(pattern string) interface{} {
|
||||
if r := j.getPointerByPattern(pattern); r != nil {
|
||||
return *r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据pattern层级查找变量指针
|
||||
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
start := 0
|
||||
index := len(pattern)
|
||||
length := 0
|
||||
pointer := j.p
|
||||
for {
|
||||
if r := j.checkPatternByPointer(pattern[start:index], pointer); r != nil {
|
||||
length += index - start
|
||||
if start > 0 {
|
||||
length += 1
|
||||
}
|
||||
start = index + 1
|
||||
index = len(pattern)
|
||||
if length == len(pattern) {
|
||||
return r
|
||||
} else {
|
||||
pointer = r
|
||||
}
|
||||
} else {
|
||||
index = strings.LastIndex(pattern[start:index], ".")
|
||||
}
|
||||
if start >= index {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断给定的pattern在当前的pointer下是否有值,并返回对应的pointer
|
||||
// 注意这里返回的指针都是临时变量的内存地址
|
||||
func (j *Json) checkPatternByPointer(pattern string, pointer *interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if v, ok := (*pointer).(map[string]interface{})[pattern]; ok {
|
||||
return &v
|
||||
}
|
||||
case []interface{}:
|
||||
if isNumeric(pattern) {
|
||||
n, err := strconv.Atoi(pattern)
|
||||
if err == nil && len((*pointer).([]interface{})) > n {
|
||||
return &(*pointer).([]interface{})[n]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 转换为map[string]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Json) ToMap() map[string]interface{} {
|
||||
switch (*(p.value)).(type) {
|
||||
func (j *Json) ToMap() map[string]interface{} {
|
||||
switch (*(j.p)).(type) {
|
||||
case map[string]interface{}:
|
||||
return (*(p.value)).(map[string]interface{})
|
||||
return (*(j.p)).(map[string]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为[]interface{}类型,如果转换失败,返回nil
|
||||
func (p *Json) ToArray() []interface{} {
|
||||
switch (*(p.value)).(type) {
|
||||
func (j *Json) ToArray() []interface{} {
|
||||
switch (*(j.p)).(type) {
|
||||
case []interface{}:
|
||||
return (*(p.value)).([]interface{})
|
||||
return (*(j.p)).([]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Json) ToXml(rootTag...string) ([]byte, error) {
|
||||
return gxml.Encode(p.ToMap(), rootTag...)
|
||||
func (j *Json) ToXml(rootTag...string) ([]byte, error) {
|
||||
return gxml.Encode(j.ToMap(), rootTag...)
|
||||
}
|
||||
|
||||
func (p *Json) ToXmlIndent(rootTag...string) ([]byte, error) {
|
||||
return gxml.EncodeWithIndent(p.ToMap(), rootTag...)
|
||||
func (j *Json) ToXmlIndent(rootTag...string) ([]byte, error) {
|
||||
return gxml.EncodeWithIndent(j.ToMap(), rootTag...)
|
||||
}
|
||||
|
||||
func (p *Json) ToJson() ([]byte, error) {
|
||||
return Encode(*(p.value))
|
||||
func (j *Json) ToJson() ([]byte, error) {
|
||||
return Encode(*(j.p))
|
||||
}
|
||||
|
||||
func (p *Json) ToJsonIndent() ([]byte, error) {
|
||||
return json.MarshalIndent(*(p.value), "", "\t")
|
||||
func (j *Json) ToJsonIndent() ([]byte, error) {
|
||||
return json.MarshalIndent(*(j.p), "", "\t")
|
||||
}
|
||||
|
||||
func (p *Json) ToYaml() ([]byte, error) {
|
||||
return gyaml.Encode(*(p.value))
|
||||
func (j *Json) ToYaml() ([]byte, error) {
|
||||
return gyaml.Encode(*(j.p))
|
||||
}
|
||||
|
||||
func (p *Json) ToToml() ([]byte, error) {
|
||||
return gtoml.Encode(*(p.value))
|
||||
func (j *Json) ToToml() ([]byte, error) {
|
||||
return gtoml.Encode(*(j.p))
|
||||
}
|
||||
|
||||
// 判断所给字符串是否为数字
|
||||
|
||||
@ -6,20 +6,42 @@ import (
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := `{
|
||||
"users" : {
|
||||
"count" : 100,
|
||||
"list" : [
|
||||
{"name" : "小明", "score" : 60},
|
||||
{"name" : "John", "score" : 99.5}
|
||||
]
|
||||
func getByPattern() {
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100,
|
||||
"list" : [
|
||||
{"name" : "小明", "score" : 60},
|
||||
{"name" : "John", "score" : 99.5}
|
||||
]
|
||||
}
|
||||
}`
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("John Score:", j.GetFloat32("users.list.1.score"))
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在"."号时,检索优先级:键名->层级,因此不会引起歧义
|
||||
func testMultiDots() {
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
},
|
||||
"users.count" : 101
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("Users Count:", j.GetInt("users.count"))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
testMultiDots()
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"encoding/json"
|
||||
"log"
|
||||
)
|
||||
|
||||
// go test json_test.go -bench=".*"
|
||||
|
||||
var data = `[{"CityId":1, "CityName":"北京", "ProvinceId":1, "CityOrder":1}, {"CityId":5, "CityName":"成都", "ProvinceId":27, "CityOrder":1}]`
|
||||
|
||||
func BenchmarkJsonDecode(b *testing.B) {
|
||||
b.N = 1000000
|
||||
for i := 0; i < b.N; i++ {
|
||||
gjson.Decode(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkJsonDecodeByUnmarshal(b *testing.B) {
|
||||
b.N = 1000000
|
||||
for i := 0; i < b.N; i++ {
|
||||
var citys interface{}
|
||||
if err := json.Unmarshal([]byte(data), &citys); err != nil {
|
||||
log.Fatalf("JSON unmarshaling failed: %s", err)
|
||||
}
|
||||
//fmt.Println(citys)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,28 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c1 := make(chan int, 2)
|
||||
c2 := make(chan int, 5)
|
||||
c1 <- 1
|
||||
c1 <- 2
|
||||
c2 = c1
|
||||
c2 <- 3
|
||||
fmt.Println(<-c2)
|
||||
fmt.Println(<-c2)
|
||||
fmt.Println(<-c2)
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
}
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
j.Set("users.count", 1)
|
||||
j.Set("users.list", []string{"John", "小明"})
|
||||
j.Set("users.0", "a")
|
||||
fmt.Println(j.Get("users.count"))
|
||||
fmt.Println(j.Get("users.count"))
|
||||
//fmt.Println(j.Get("users.list"))
|
||||
c, _ := j.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
}
|
||||
17
geg/other/test2.go
Normal file
17
geg/other/test2.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//var v interface{}
|
||||
m := map[string]int {
|
||||
"age" : 18,
|
||||
}
|
||||
//v = m
|
||||
p := &m
|
||||
(*p)["age"] = 16
|
||||
//fmt.Println(v)
|
||||
fmt.Println(m)
|
||||
}
|
||||
Reference in New Issue
Block a user