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, " ", "") 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("反序列化之前: s1 = %v s1.Name = %s ", 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("反序列化之后: s1 = %v s1.Name = %s ", 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