Go - 37 Go Json的序列化/反序列化 应用
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。同时也易于机器解析和生成;key-val
JSON是在2001年开始推广使用的数据格式,目前已经成为主流的数据格式。
JSON易于机器解析和生成,并有效地提升网络传输效率,通常程序在网络传输时会先将数据(结构体/map等)序列化成json字符串,到接收方得到json字符串时,在反序列化恢复成原来的数据类型(结构体/map等)。这种方式已然成为各个语言的标准。
JSON应用场景:
web编程中应用 : B/S 架构
tcp编程中的应用:聊天系统 C/S 架构
JSON数据格式说明:
在js语言中,一切都是对象,因此,任何的数据类型都可以通过JSON来表示,例如:字符串,数字,对象,数组,map ,结构体等。
JSON键值对是用来保存数据一种的方式,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号:分割,然后紧接着值;
json数据在线解析网站:https://www.json.cn/
Json序列化:
json序列化是指,将有key-value结构的数据类型(比如结构体,map,切片)序列化成json字符串的操作
操作案例:
需要用到的包:"encoding/json"
// 定义一个结构体 + tag标签(反射机制)(Marshal--序列化数据会涉及跨包使用,所以得用大写,然后加tag标签)
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
// Name string
// Age int
Birthday string
Sal float64
Skill string
}
// 将结构体序列化
func testStruct() {
m := Monster{
Name: "孙悟空",
Age : 500,
Birthday: "2020-12-28",
Sal : 20000.0,
Skill : "七十二变",
}
// 将Monster 实例 序列化
m_slice, err := json.Marshal(&m)
if err != nil {
fmt.Println("序列化出错==", err)
}
// 序列化后的结果
fmt.Println(string(m_slice))
}
// 将map序列化
func testMap() {
// 定义一个map
var a map[string]interface{}
// 使用map,需要make
a = make(map[string]interface{})
a["name"] = "沙和尚"
a["age"] = 200
a["address"] = "流沙河"
// 将 a map类型序列化 map 本身就是引用类型,所以 不用传地址
a_slice, err := json.Marshal(a)
if err != nil {
fmt.Println("a map 序列化出错=", err)
}
// a map 序列化后的结果
fmt.Println("a map json==", string(a_slice))
}
// 将切片序列化
func testSlice() {
// slice map 都需要make才能用
var s []map[string]interface{}
s = make([]map[string]interface{}, 2, 4)
s[0] = make(map[string]interface{})
s[0]["name"] = "tom"
s[0]["age"] = 30
s[0]["address"] = []string{"北京", "邯郸"}
s[1] = make(map[string]interface{})
s[1]["name"] = "marry"
s[1]["age"] = 28
s[1]["address"] = "北京"
s_slice, err := json.Marshal(s)
if err != nil {
fmt.Println("s slice 序列化出错=", err)
}
// 序列化后的结果
fmt.Println("s slice json=", string(s_slice)) }
// 基本数据类型的序列化
func baseTest() {
var num1 float64 = 232423.20
data, err := json.Marshal(num1)
if err != nil {
fmt.Println("num1 序列化出错=", err)
}
// 序列化后的结果
fmt.Println("num1 json=", string(data))
}
func main() {
// 将结构体,map,切片 进行序列化
testStruct()
testMap()
testSlice()
// 对基本数据类型序列化在实际中意义不大
baseTest()
}
Json反序列化:
json反序列化是指,将json字符串反序列化成对应的数据类型(比如结构体,map,切片)的操作。
实际案例:
// 定义一个结构体 用来解析json串
type Monster struct {
Name string
Age int
Birthday string
Sal float64
Skill string
}
// 将json字符串,反序列化成struct
func unmarshalStruct() {
// str 在项目开发中,是通过网络传输获取到的,或者是读取文件获取到的
str := "{\"Name\":\"孙悟空\",\"Age\":500,\"Birthday\":\"2020-12-28\",\"Sal\":20000,\"Skill\":\"七十二变\"}"
// 定义一个Monster实例
var m Monster
// Unmarshal两个参数:第一个接收json的数据--> byte切片 第二个参数:根据json数据要改变的Monster实例 err := json.Unmarshal([]byte(str), &m)
if err != nil {
fmt.Println("unmarshal err=", err)
}
fmt.Println("struct 反序列化后 m=", m, m.Name)
}
// json数据 反序列化成map
func unmarshalMap() {
str := "{\"address\":\"流沙河\",\"age\":200,\"name\":\"沙和尚\"}"
// 定义一个map
var a map[string]interface{}
// 注意:反序列化map,不需要make,因为make操作被封装到Unmarshal 函数
err := json.Unmarshal([]byte(str), &a)
if err != nil {
fmt.Println("map unmarshal err==", err)
}
fmt.Println("map 反序列化后=", a)
}
// json数据,反序列化成切片
func unmarshalSlice() {
str := "[{\"address\":[\"北京\",\"邯郸\"],\"age\":30,\"name\":\"tom\"}," + "{\"address\":\"北京\",\"age\":28,\"name\":\"marry\"}]"
var s []map[string]interface{}
err := json.Unmarshal([]byte(str), &s)
if err != nil {
fmt.Println("slice unmarshal err=", err)
}
fmt.Println("slice 反序列化=", s)
}
func main() {
// unmarshal
unmarshalStruct()
unmarshalMap()
unmarshalSlice()
}
小结说明:
1.在反序列化一个json字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。
2.如果json字符串是通过程序获取到的,则不需要再对 "" 转义处理。