json库

json库

json结构体从b复制到a

json.Marshal(query)  # 转换为json字符串
json.Unmarshal(strquery)  # json字符串转换为标准json

//a,b结构体不一样,从b复制到a
a:=A{}
bStr, _ := json.Marshal(b)
_ = json.Unmarshal(bStr, &a)

strings.Join字符串拼接

var NetworkSql string
for i := range in.Network {
  NetworkSql = strings.Join([]string{NetworkSql, strconv.Itoa(in.Network[i])}, ",")
}
NetworkSql = string(NetworkSql)[1:]

json字符串转换

import "encoding/json"
json.Marshal(query)  # 转换为json字符串
json.Unmarshal(strquery)  # json字符串转换为标准json


type Student struct {
	Name    string
	Age     int
	Classes []string
	Price   float32
}



func main() {

	st := &Student {
		"jeff",
		18,
		[]string{"math", "English", "Chinese"},
		9.99,
	}
	b, _ := json.Marshal(st)
	fmt.Println(string(b))  //{"Name":"jeff","Age":18,"Classes":["math","English","Chinese"],"Price":9.99}

	stb := &Student{}
	_ = json.Unmarshal([]byte(b), &stb)
	fmt.Println(stb) //&{jeff 18 [math English Chinese] 9.99}
}

redis map转结构体

package main

import (
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis"
)

var rdb *redis.Client

func initClient() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "127.0.0.1",
		Password: "", // no password set
		DB:       4,  // use default DB
	})

	_, err = rdb.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

type bike struct {
	Acc string `json:"acc"`
	CcID string `json:"cc_id"`
}

func main() {
	err := initClient()
	if err != nil {
		fmt.Println(err)
	}
	value, err2 := rdb.HGetAll("br:10066").Result()
	if err2 != nil {
		fmt.Println(err2)
	}
	//fmt.Printf("%T",value) //map[string]string
	//fmt.Println(value)
	//// 遍历每一个字段
	//a:=value["cc_id"]
	//fmt.Println(a) // 10066
	//// 每一个字段一个个初始化,怎么样可以直接传入&bike,自动初始化
	//b := bike{
	//	Cc_id: a,
	//}
	//fmt.Printf("%+v",b) // {cc_id:10066}

	//var src []map[string]string

	json_ret, err := json.Marshal(value)
	if err != nil {
		fmt.Println(err)
	}
	var bike_test bike
	err = json.Unmarshal(json_ret, &bike_test)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%+v", bike_test)
}

json结构体转interface

b, _ := json.Marshal(&traveList)
var m []interface{}
_ = json.Unmarshal(b, &m)


//2. omitempty忽略零值和nil值
type User struct {
		Name string `json:"name,omitempty"`
		Age  int    `json:"age,omitempty"`
	}
	jeff := User{
		Name: "Jeff",
	}
	fmt.Println(jeff)

	b, _ := json.Marshal(&jeff)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	fmt.Println(m) //map[name:Jeff]

json字符串转结构体

例子1:

type Info struct {
	Id      int    `json:"id"`
	Code    string `json:"code"`
	HwCode  string `json:"hw_code"`
	Name    string `json:"name"`
	BrandId int    `json:"brand_id"`
}

func jsonTest1()  {
	jsonStr := `{"id":2,"code":"W01","hw_code":"AA5","name":"秋月白","brand_id":1}`
	r:=Info{}
	str:=[]byte(jsonStr)
	json.Unmarshal([]byte(str),&r)
	fmt.Println(r) //{2 W01 AA5 秋月白 1}
}

例子2:[{},{},{}]

type Info struct {
	Id      int    `json:"id"`
	Code    string `json:"code"`
	HwCode  string `json:"hw_code"`
	Name    string `json:"name"`
	BrandId int    `json:"brand_id"`
}

func jsonTest2()  {
	jsonStr := `[{"id":2,"code":"W01","hw_code":"AA5","name":"秋月白","brand_id":1},{"id":3,"code":"W02","hw_code":"AA6","name":"秋月黑","brand_id":2}]`
	r:=Info{}
	list := make([]Info,0)
	var li []map[string]interface{}
	json.Unmarshal([]byte(jsonStr),&li)
	for _,v:=range li{
		arr,_:=json.Marshal(v)
		json.Unmarshal(arr,&r)
		list = append(list, r)
	}
	fmt.Println(list) // [{2 W01 AA5 秋月白 1} {3 W02 AA6 秋月黑 2}]
}

例子3:map[],redis hash

type bike struct {
	Acc string `json:"acc"`
	CcID string `json:"cc_id"`
}

func jsonTest3()  {
	err := initClient()
	if err != nil {
		fmt.Println(err)
	}
	value, err2 := rdb.HGetAll("br:10066").Result()

	if err2 != nil {
		fmt.Println(err2)
	}
	fmt.Println(value)
	json_ret, err := json.Marshal(value)
	if err != nil {
		fmt.Println(err)
	}
	var bike_test bike
	err = json.Unmarshal(json_ret, &bike_test)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%+v", bike_test)
}

通过结构体生成json

buf, err := json.MarshalIndent(s, "", " ") //格式化编码

package main

import (
	"encoding/json"
	"fmt"
)

//成员变量名首字母必须大写
type IT struct {
	Company  string   `json:"-"`        //此字段不会输出到屏幕
	Subjects []string `json:"subjects"` //二次编码
	IsOk     bool     `json:",string"`
	Price    float64  `json:",string"`
}

func main() {
	//定义一个结构体变量,同时初始化
	s := IT{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.666}

	//编码,根据内容生成json文本
	//{"Company":"itcast","Subjects":["Go","C++","Python","Test"],"IsOk":true,"Price":666.666}
	//buf, err := json.Marshal(s)
	buf, err := json.MarshalIndent(s, "", "	") //格式化编码
	if err != nil {
		fmt.Println("err = ", err)
		return
	}
	fmt.Println(string(buf))
}

通过map生成json

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	//创建一个map
	m := make(map[string]interface{}, 4)
	m["company"] = "itcast"
	m["subjects"] = []string{"Go", "C++", "Python", "Test"}
	m["isok"] = true
	m["price"] = 666.666

	//编码成json
	//result, err := json.Marshal(m)
	result, err := json.MarshalIndent(m, "", "	")
	if err != nil {
		fmt.Println("err = ", err)
		return
	}
	fmt.Println("result = ", string(result))
}

json解析到结构体

err := json.Unmarshal([]byte(jsonBuf), &tmp) //第二个参数要地址传递

package main

import (
	"encoding/json"
	"fmt"
)

type IT struct {
	Company  string   `json:"company"`
	Subjects []string `json:"subjects"` //二次编码
	IsOk     bool     `json:"isok"`
	Price    float64  `json:"price"`
}

func main() {

	jsonBuf := `
	{
    "company": "itcast",
    "subjects": [
        "Go",
        "C++",
        "Python",
        "Test"
    ],
    "isok": true,
    "price": 666.666
}`

	var tmp IT                                   //定义一个结构体变量
	err := json.Unmarshal([]byte(jsonBuf), &tmp) //第二个参数要地址传递
	if err != nil {
		fmt.Println("err = ", err)
		return
	}
	//fmt.Println("tmp = ", tmp)
	fmt.Printf("tmp = %+v\n", tmp)

	type IT2 struct {
		Subjects []string `json:"subjects"` //二次编码
	}

	var tmp2 IT2
	err = json.Unmarshal([]byte(jsonBuf), &tmp2) //第二个参数要地址传递
	if err != nil {
		fmt.Println("err = ", err)
		return
	}
	fmt.Printf("tmp2 = %+v\n", tmp2)

}

json解析到map

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	jsonBuf := `
	{
    "company": "itcast",
    "subjects": [
        "Go",
        "C++",
        "Python",
        "Test"
    ],
    "isok": true,
    "price": 666.666
}`

	//创建一个map
	m := make(map[string]interface{}, 4)

	err := json.Unmarshal([]byte(jsonBuf), &m) //第二个参数要地址传递
	if err != nil {
		fmt.Println("err = ", err)
		return
	}
	fmt.Printf("m = %+v\n", m)

	//	var str string
	//	str = string(m["company"]) //err, 无法转换
	//	fmt.Println("str = ", str)

	var str string

	//类型断言, 值,它是value类型
	for key, value := range m {
		//fmt.Printf("%v ============> %v\n", key, value)
		switch data := value.(type) {
		case string:
			str = data
			fmt.Printf("map[%s]的值类型为string, value = %s\n", key, str)
		case bool:
			fmt.Printf("map[%s]的值类型为bool, value = %v\n", key, data)
		case float64:
			fmt.Printf("map[%s]的值类型为float64, value = %f\n", key, data)
		case []string:
			fmt.Printf("map[%s]的值类型为[]string, value = %v\n", key, data)
		case []interface{}:
			fmt.Printf("map[%s]的值类型为[]interface, value = %v\n", key, data)
		}

	}

}

使用jsoniter库效率更高

地址:https://github.com/json-iterator/go

使用:
import (
	jsoniter "github.com/json-iterator/go"
)

对比:

与标准库 100% 兼容,提示4倍
性能对比

解析性能(Parse):
Jsoniter 的解析性能通常比标准 JSON 库快 2-3 倍。
在某些场景下, Jsoniter 的解析速度可以达到标准 JSON 库的 5-10 倍。

序列化性能(Serialize):
Jsoniter 的序列化性能通常比标准 JSON 库快 2-4 倍。
在某些场景下, Jsoniter 的序列化速度可以达到标准 JSON 库的 5-20 倍。

内存占用:
Jsoniter 的内存占用通常比标准 JSON 库低 20-50%。

优化地方:

内存池技术:
标准 JSON 库在解析和序列化过程中,需要频繁申请和释放内存,产生大量的内存碎片。
Jsoniter 采用内存池技术,复用内存块,减少了内存分配和释放的开销,从而提升性能并降低内存占用。

高效的解析算法:
Jsoniter 使用了更加高效的 JSON 解析算法,比如流式解析和并行解析等,相比标准库有明显的性能优势。

零拷贝特性:
在某些场景下,Jsoniter 能够实现零拷贝的序列化和反序列化,避免了不必要的数据复制,进一步提升性能

编译器优化支持:
Jsoniter 的代码生成过程能够充分利用现代编译器的优化功能,进一步提升性能

gjson--从json字符串中取值

可以方便地从一个 JSON 串中读取值。同时它也支持各种查询、汇总统计等功能

参考:https://darjun.github.io/2020/03/22/godailylib/gjson/

对应还有个设置json的,但是设置字符串json的场景很少:https://darjun.github.io/2020/03/24/godailylib/sjson/

先安装:
$ go get github.com/tidwall/gjson

1.key匹配

package main

import (
	"fmt"
	"github.com/tidwall/gjson"
)

func main() {
	json := `{"name":"jeff","name2":"jeff2","age":28,"girlfriendList":[{"name":"小花","age":18},{"name":"小静","age":20},{"name":"小蕊","age":24}]}`

	//1.key取值
	name := gjson.Get(json, "name")
	girlfriendList := gjson.Get(json, "girlfriendList")
	fmt.Println(name.String())          //jeff
	fmt.Println(girlfriendList.Array()) //[{"name":"小花","age":18} {"name":"小静","age":20} {"name":"小蕊","age":24}]
}

2.数组操作* ?匹配

json := `{"name":"jeff","name2":"jeff2","age":28,"girlfriendList":[{"name":"小花","age":18},{"name":"小静","age":20},{"name":"小蕊","age":24}]}`

//2.数组操作 *匹配任意多个字符,?匹配单个字符
info1 := gjson.Get(json, "girlfriendList.0") //数组下标取值
fmt.Println(info1)                           //{"name":"小花","age":18}

info2 := gjson.Get(json, "girlfriendList.0.name") //数组下标+key取值
fmt.Println(info2)                                //小花

info3 := gjson.Get(json, "girlfriendList.#") //数组长度
fmt.Println(info3)                           //3

info4 := gjson.Get(json, "name?") //? 匹配单个字符
fmt.Println(info4)                //jeff2

info5 := gjson.Get(json, "girlfriendList.#.name") //? 匹配数组
fmt.Println(info5)                                //["小花","小静","小蕊"]

info6 := gjson.GetMany(json, "name", "girlfriendList.#.name", "girlfriendList.#.age") //? GetMany一次取多个值
fmt.Println(info6)    

3.按照条件匹配

json := `{"name":"jeff","name2":"jeff2","age":28,"girlfriendList":[{"name":"小花","age":18},{"name":"小静","age":20},{"name":"小蕊","age":24}]}`
//3.按照条件匹配
info7 := gjson.Get(json, "girlfriendList.#(age>=24)#") //条件匹配
fmt.Println(info7)                                     //[{"name":"小蕊","age":24}]

info8 := gjson.Get(json, "girlfriendList.#(age>=20)#.name") //条件匹配 >=
fmt.Println(info8)                                          //["小静","小蕊"]

info9 := gjson.Get(json, `girlfriendList.#(name%"*蕊*")#`) //条件匹配 %
fmt.Println(info9)      

4.修饰符

修饰符是gjson提供的非常强大的功能,和键路径搭配使用。gjson提供了一些内置的修饰符:

@reverse:翻转一个数组;
@ugly:移除 JSON 中的所有空白符;
@pretty:使 JSON 更易用阅读,json格式化;
@this:返回当前的元素,可以用来返回根元素;
@valid:校验 JSON 的合法性;
@flatten:数组平坦化,即将["a", ["b", "c"]]转为["a","b","c"];
@join:将多个对象合并到一个对象中。
修饰符的语法和管道类似,以|分隔键路径和分隔符。

使用

import (
	"fmt"
	"github.com/tidwall/gjson"
)

func main() {
	json := `{"name":"jeff","name2":"jeff2  ","age":28,"girlfriendList":[{"name":"小花 ","age":18},{"name":"小静","age":20},{"name":"小蕊","age":24}]}`

	info1 := gjson.Get(json, "girlfriendList|@reverse") //翻转数组--输出全部
	fmt.Println(info1)                                  //[{"name":"小蕊","age":24},{"name":"小静","age":20},{"name":"小花 ","age":18}]

	info2 := gjson.Get(json, "girlfriendList|@reverse|0") //翻转数组--输出下标第0个
	fmt.Println(info2)                                    //{"name":"小蕊","age":24}

	info3 := gjson.Get(json, "name2|@ugly") //ugly 移除 JSON 中的所有空白符
	fmt.Println(info3)                      //jeff2

	info4 := gjson.Get(json, "girlfriendList|@pretty") //json格式化
	fmt.Println(info4)

	nestedJSON := `{"nested": ["one", "two", ["three", "four"]]}`
	fmt.Println(gjson.Get(nestedJSON, "nested|@flatten")) //数组平坦化

	userJSON := `{"info":[{"name":"dj", "age":18},{"phone":"123456789","email":"dj@example.com"}]}` //将多个对象合并到一个对象中
	fmt.Println(gjson.Get(userJSON, "info|@join"))                                                  // {"name":"dj","age":18,"phone":"123456789","email":"dj@example.com"}
  
  info := gjson.Get(json, `girlfriendList|@reverse:{"age":true}`) //修饰符参数
	fmt.Println(info)
}

自定义修饰符

如此强大的功当然要支持自定义!gjson使用AddModifier()添加一个修饰符,传入一个名字和类型为func(json arg string) string的处理函数。处理函数接受待处理的 JSON 值和修饰符参数,返回处理后的结果。下面编写一个转换大小写的修饰符:

func main() {
  gjson.AddModifier("case", func(json, arg string) string {
    if arg == "upper" {
      return strings.ToUpper(json)
    }

    if arg == "lower" {
      return strings.ToLower(json)
    }

    return json
  })

  const json = `{"children": ["Sara", "Alex", "Jack"]}`
  fmt.Println(gjson.Get(json, "children|@case:upper"))
  fmt.Println(gjson.Get(json, "children|@case:lower"))
}

5.JSON 行

gjson提供..语法可以将多行数据看成一个数组,每行数据是一个元素:

import (
	"fmt"
	"github.com/tidwall/gjson"
)

const json = `
{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}`

func main() {
	fmt.Println(gjson.Get(json, "..#"))                 //返回有多少行 JSON 数据;4
	fmt.Println(gjson.Get(json, "..0"))                 //返回第0行;{"name": "Gilbert", "age": 61}
	fmt.Println(gjson.Get(json, "..#.name"))            //每个name组成数组;["Gilbert","Alexa","May","Deloise"]
	fmt.Println(gjson.Get(json, `..#(name="May").age`)) //取name为"May"的行中的age字段;57
}

6.遍历json

import (
	"fmt"
	"github.com/tidwall/gjson"
)

const json = `
{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
{"name": "Deloise", "age": 44}`

func main() {
	gjson.ForEachLine(json, func(line gjson.Result) bool {
		fmt.Println("name:", gjson.Get(line.String(), "name"))
		return true
	})
}


//输出
name: Gilbert
name: Alexa
name: May
name: Deloise

案例2:

const json = `
{
  "name":"dj",
  "age":18,
  "pets": ["cat", "dog"],
  "contact": {
    "phone": "123456789",
    "email": "dj@example.com"
  }
}`

func main() {
	pets := gjson.Get(json, "pets")
	pets.ForEach(func(_, pet gjson.Result) bool {
		fmt.Println(pet)
		return true
	})

	contact := gjson.Get(json, "contact")
	contact.ForEach(func(key, value gjson.Result) bool {
		fmt.Println(key, value)
		return true
	})
}

7.校验json是否合法

调用gjson.Get()时,gjson假设我们传入的 JSON 串是合法的。如果 JSON 非法也不会panic,这时会返回不确定的结果:

们可以使用gjson.Valid()检测 JSON 串是否合法:

import (
	"fmt"
	"github.com/tidwall/gjson"
)

func main() {
	const json = `{"name":dj,age:18}`
	fmt.Println(gjson.Get(json, "name")) //非法输出18,实际json不合法

	if !gjson.Valid(json) {
		fmt.Println("error")
	} else {
		fmt.Println("ok")
	}
}
posted @ 2023-10-06 21:06  Jeff的技术栈  阅读(60)  评论(1编辑  收藏  举报
回顶部