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")
}
}
选择了IT,必定终身学习