Golang的序列化-JSON篇
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.序列化概述
1>.什么是序列化
数据在网络传输前后要进行序列化和反序列化。目的是将复杂的数据类型按照统一、简单且高效的形式转储,以达到网络传输的目的。
除了在网络传输,有的数据存储到本地也是为了其它语言使用方便,通常也会使用相对来说较为通用的数据格式来存储,这就是我们常说的序列化,反序列化就是将数据按照规定的语法格式进行解析的过程。
2>.什么是JSON
JSON采用完全独立于语言的文本格式,但是也使用了类似于 C 语言家族的习惯(包括 C、C++、C#、Java、JavaScript、Perl、Python、go等)。这些特性使JSON成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。目前,json已经成为主流的数据格式。
JSON的特性:
a).JSON解析器和JSON库支持许多不同的编程语言。
b).JSON文本格式在语法上与创建JavaScript对象的代码相同。由于这种相似性,无需解析器,JavaScript程序能够使用内建的eval()函数,用JSON数据来生成原生的JavaScript对象。
c).JSON 是存储和交换文本信息的语法。比 XML 更小、更快,更易解析。
d).JSON 具有自我描述性,语法简洁,易于理解。
e).JSON数据主要有两种数据结构,一种是键/值,另一种是数组的形式来表示。
博主推荐阅读:
http://www.json.org.cn/
二.JSON序列化案例
1>.结构体序列化
package main
import (
"encoding/json"
"fmt"
)
/**
定义需要结构体
*/
type Teacher struct {
Name string
ID int
Age int
Address string
}
func main() {
s1 := Teacher{
Name: "Jason Yin",
ID: 001,
Age: 18,
Address: "北京",
}
/**
使用“encoding/json”包的Marshal函数进行序列化操作,其函数签名如下所示:
func Marshal(v interface{}) ([]byte, error)
以下是对Marshal函数参数相关说明:
v:
该参数是空接口类型。意味着任何数据类型(int、float、map,结构体等)都可以使用该函数进行序列化。
返回值:
很明显返回值是字节切片和错误信息
*/
//data, err := json.Marshal(&s1)
/**
Go语言标准库的"encoding/json"包还提供了另外一个方法:MarshalIndent。
该方法的作用与Marshall作用相同,只是可以通过方法参数,设置前缀、缩进等,对Json多了一些格式处理,打印出来比较好看。
*/
data, err := json.MarshalIndent(s1, "\t", "")
if err != nil {
fmt.Println("序列化出错,错误原因: ", err)
return
}
/**
查看序列化后的json字符串
*/
fmt.Println("序列化之后的数据为: ", string(data))
}
package main
import (
"encoding/json"
"fmt"
)
/**
定义需要结构体
*/
type Teacher struct {
Name string
ID int
Age int
Address string
}
func main() {
s1 := Teacher{
Name: "Jason Yin",
ID: 001,
Age: 18,
Address: "北京",
}
/**
使用“encoding/json”包的Marshal函数进行序列化操作,其函数签名如下所示:
func Marshal(v interface{}) ([]byte, error)
以下是对Marshal函数参数相关说明:
v:
该参数是空接口类型。意味着任何数据类型(int、float、map,结构体等)都可以使用该函数进行序列化。
返回值:
很明显返回值是字节切片和错误信息
*/
data, err := json.Marshal(&s1) //注意哈,这里传递的是引用地址哟~
if err != nil {
fmt.Println("序列化出错,错误原因: ", err)
return
}
/**
查看序列化后的json字符串
*/
fmt.Println("序列化之后的数据为: ", string(data))
}

2>.Map序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
var s1 map[string]interface{}
/**
使用make函数初始化map以开辟内存空间
*/
s1 = make(map[string]interface{})
/**
map赋值操作
*/
s1["name"] = "Jason Yin"
s1["age"] = 20
s1["address"] = [2]string{"北京", "陕西"}
/**
将map使用Marshal()函数进行序列化
*/
data, err := json.Marshal(s1)
if err != nil {
fmt.Println("Marshal err: ", err)
return
}
/**
查看序列化后的json字符串
*/
fmt.Println("序列化之后的数据为: ", string(data))
}

3>.切片(sllice)序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
/**
创建一个类似于map[string]interface{}的切片
*/
var s1 []map[string]interface{}
/**
使用make函数初始化map以开辟内存空间,
*/
m1 := make(map[string]interface{})
/**
为map进行赋值操作
*/
m1["name"] = "李白"
m1["role"] = "打野"
m2 := make(map[string]interface{})
m2["name"] = "王昭君"
m2["role"] = "中单"
m3 := make(map[string]interface{})
m3["name"] = "程咬金"
m3["role"] = "上单"
/**
将map追加到切片中
*/
s1 = append(s1, m3, m2, m1)
data, err := json.Marshal(s1)
if err != nil {
fmt.Println("序列化出错,错误原因: ", err)
return
}
/**
查看序列化后的数据
*/
fmt.Println(string(data))
}

4>.数组序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
/**
定义数组
*/
var s1 = [5]int{9, 5, 2, 7, 5200}
/**
将数组使用Marshal函数进行序列化
*/
data, err := json.Marshal(s1)
if err != nil {
fmt.Println("序列化错误: ", err)
return
}
/**
查看序列化后的json字符串
*/
fmt.Println("数组序列化后的数据为: ", string(data))
}

5>.基础数据类型序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
/**
定义基础数据类型数据
*/
var (
Surname = '尹'
Name = "尹正杰"
Age = 18
Temperature = 35.6
HubeiProvince = false
)
/**
将基础数据类型进行序列化操作
*/
surname, _ := json.Marshal(Surname)
name, _ := json.Marshal(Name)
age, _ := json.Marshal(Age)
temperature, _ := json.Marshal(Temperature)
hubeiProvince, _ := json.Marshal(HubeiProvince)
/**
查看序列化后的json字符串
*/
fmt.Println("Surname序列化后的数据为: ", string(surname))
fmt.Println("Name序列化后的数据为: ", string(name))
fmt.Println("Age序列化后的数据为: ", string(age))
fmt.Println("Temperature序列化后的数据为: ", string(temperature))
fmt.Println("HubeiProvince序列化后的数据为: ", string(hubeiProvince))
}

三.JSON反序列化案例
1>.结构体反序列化
package main
import (
"encoding/json"
"fmt"
)
type People struct {
Name string
Age int
Address string
}
func main() {
/**
以Json数据为例,我们接下来要对该数据进行反序列化操作。
*/
p1 := `{"Name":"Jason Yin","Age":18,"Address":"北京"}`
var s1 People
fmt.Printf("反序列化之前: \n\ts1 = %v \n\ts1.Name = %s\n\n", s1, s1.Name)
/**
使用encoding/json包中的Unmarshal()函数进行反序列化操作,其函数签名如下:
func Unmarshal(data []byte, v interface{}) error
以下是对函数签名的参数说明:
data:
待解析的json编码字符串
v:
解析后传出的结果,即用来可以容纳待解析的json数据容器.
*/
err := json.Unmarshal([]byte(p1), &s1)
if err != nil {
fmt.Println("反序列化失败: ", err)
return
}
/**
查看反序列化后的结果
*/
fmt.Printf("反序列化之后: \n\ts1 = %v \n\ts1.Name = %s\n", s1, s1.Name)
}

2>.map反序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
m1 := `{"address":["北京","陕西"],"age":20,"name":"Jason Yin"}`
/**
定义map变量,类型必须与之前序列化的类型完全一致。
*/
var s1 map[string]interface{}
fmt.Println("反序列化之前:s1 =", s1)
/**
温馨提示:
不需要使用make函数给m初始化,开辟空间。这是因为在反序列化函数Unmarshal()中会判断传入的参数2,如果是map类型数据,会自动开辟空间。相当于是Unmarshal()函数可以帮助我们做make操作。
但传参时需要注意,Unmarshal的第二个参数,是用作传出,返回结果的。因此必须传m的地址值。
*/
err := json.Unmarshal([]byte(m1), &s1)
if err != nil {
fmt.Println("反序列化失败,错误原因: ", err)
return
}
fmt.Println("反序列化之后:s1 =", s1)
}

3>.切片(slice)反序列化
package main
import (
"encoding/json"
"fmt"
)
func main() {
s1 := `[{"name":"王昭君","role":"中单"},{"name":"李白","role":"打野"}]`
var slice []map[string]interface{}
fmt.Println("反序列化之前:slice =", slice)
/**
实现思路与前面两种的实现完全一致,这里不再赘述。
温馨提示:
反序列化json字符串时,务必确保反序列化传出的数据类型,与之前序列化的数据类型完全一致。
*/
err := json.Unmarshal([]byte(s1), &slice)
if err != nil {
fmt.Println("反序列化失败,错误原因: ", err)
return
}
fmt.Println("反序列化之后:slice =", slice)
}

四.结构体标签(tag)序列化
package main
import (
"encoding/json"
"fmt"
)
/**
结构体的字段除了名字和类型外,还可以有一个可选的标签(tag),它是一个附属于字段的字符串,可以是文档或其他的重要标记。
比如在我们解析json或生成json文件时,常用到encoding/json包,它提供一些默认标签。
定义结构体时,可以通过这些默认标签来设定结构体成员变量,使之在序列化后得到特殊的输出。
*/
type Student struct {
/**
“-”标签:
作用是不进行序列化,效果和将结构体字段首字母写成小写一样。
*/
Name string `json:"-"`
/**
string标签:
这样生成的json对象中,ID的类型转换为字符串
*/
ID int `json:"id,string"`
/**
omitempty标签:
可以在序列化的时候忽略0值或者空值;
*/
Age int `json:"AGE,omitempty"`
/**
可以将字段名称进行重命名操作:
比如下面的案例就是将"Address"字段重命名为"HomeAddress"哟~
*/
Address string `json:"HomeAddress"`
/**
由于该字段首字母是小写,因此该字段不参与序列化哟~
*/
score int
Hobby string
}
func main() {
s1 := Student{
Name: "Jason Yin",
ID: 001,
//Age: 18,
Address: "北京",
score: 100,
Hobby: "中国象棋",
}
data, err := json.Marshal(s1)
if err != nil {
fmt.Println("序列化出错,错误原因: ", err)
return
}
fmt.Println("序列化结果: ", string(data))
}

五.博主推荐阅读
Golang的序列化-Gob篇: https://www.cnblogs.com/yinzhengjie2020/p/12735277.html