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