开发者学堂课程【Go语言核心编程 - 面向对象、文件、单元测试、反射、TCP编程:反序列化介绍和应用实例】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9740
反序列化介绍和应用实例
内容介绍
一、Json 的反序列化
二、代码演示
一、Json的反序列化
1. 介绍
json反序列化是指,将json字符串反序列化成对应的数据类型(比如结构体、map.切片)的操作。(原来是结构体,序列化后为字符串通过网络传送到浏览器,浏览器收到字符串根据需要还原数组或结构体,就成为反序列化)反序列化就是序列化的逆向操作
2. 应用案例
这里介绍将 json 字符串反序列化成结构体、map 和切片。也就是将前面序列化后的结构体重新反序列化为原来的数据类型
二、代码演示
新建文件夹名为 unmashal/serial
1.反序列化成 struct
(1)代码
package main
import (
"fmt"
"encoding/ljson"
)
//定义一个结构体
type Monster struct{
Name string `json: "monster_name"//反射机制
Age int `json : "monster_age"
Birthday string // ....
sal float64
skill string
}
//演示将 json 字符串,反序列化成 struct
func unmarsha1Structo {
//说明 str 在项目开发中,是通过网络传输获取到..或者是读取文件获取到
str :="("Name\": "牛魔王\", "Age":500, "Birthdayl":1"2011-11-111","Sal\":8000,"Skil1\":\"牛魔拳\"}"
//定义一个 Monster 实例
var monster Monster
err := json.Unmarshal([]byte(str),&monster)
if err != nil {
fmt.Printf("unmarshal err=%vin", err)
}
fmt.Printf("反序列化后 monster=%v\n",monster,)
(2)注意事项
Json 字符串如何得到:
A 客户端将结构体序列化后成为字符串,后台服务器传给 B 客户端,B 客户端得到 json 字符串
反序列化前要将结构体定义拿过来,要将字符串反序列化 monster 一定要有结构体定义
unmashal 可以接收两个参数,一个参数是字符串对应 byte 切片,另外一个是将字符串反序列化过后改变哪一个结构体变量。所以要引入传递,否则无法改变值。反序列化后将数据传递给 monster
(3)运行效果
D:\go project\src\go_code\chapter14\json\unmarshal>go run main.go
反序列化后 monster=<牛魔王 500 2001-11-11 8000 牛魔拳>
D:\go project\src\go_code\chapter14\json\unmarshal>
证明反序列化成功
已经成为了结构体的变量 fmt.Printf("反序列化后monster=%v\n",monster,)可以读取每个字段,如果只想读取名字则改为 fmt.Printf("反序列化后 monster=%v\n"monster.Name=%v",monster,monster.Name)
运行查看结果
D:\go project\src\go_code\chapter14\json\unmarshal>go run main.go
反序列化后 monster=<牛魔王 >
D:\go project\src\go_code\chapter14\json\unmarshal>
2.反序列化成 map
(1)代码
//演示将 json 字符串,反序列化成 map
func unmarsha1Map() {
str := "{ \"address\":\"洪崖洞", \"age\":30,\ "name\":\"红孩儿\"}"
//定义一个 map
var a map[string]interface{}
//反序列化
//注意:反序列化 map,不需要 make,因为 make 操作被封装到 Unmarshal 函数
err := json.Unmarsha1([]byte(str),&a)
if err != nil {
fmt.Printf("unmarshal err=%v\n", err)
}
fat.Printf("反序列化后 a=%v\n",a)
func main(){
unmarshalStruct()
unmarshalMap()
}
(2)执行代码
D:\go project\src\go_code\chapter14\json\unmarshal>go run main.go
反序列化后 a=map[address:洪崖洞 age:30 name:红孩儿]
D:\go project\src\go_code\chapter14\json\unmarshal>
(3)注意事项
定义的 map 要与原来的 map 定义结构保持一致,不可以随意定义,因为序列化时是对 map 序列化的,反序列化是map 结构不能变。
反序列化不需要给 map make,因为反序列化底层会制作 map make 的空间,在函数内部已经进行了 make 操作,外部不在需要
3.反序列化成切片
(1)代码
str :="[{\"address\":\"北京\", \"age\":\"7\", \"name\":\"jack\"},"+
"{ \"address\":[\"墨西哥\",\"夏威夷\"]. \"age\":\"20\", \"name\": \"tom\"}]"
//定义一个 slice
var slice [Jm ap[string]interface{}
//反序列化,不需要 make,因为 make 操作被封装到 Unmarshal 函数
err := json.Unmarsha1([]byte(str),&slice)
if err != nil {
fmt.Printf("unmarshal err=%vin", err)
}
fmt.Printf("反序列化后 slice=%v\n", slice)
}
func main()
unmarshalSlice()
(2)注意事项
程序读取到的反序列化字符串不需要一个一个加转义符,字符串过长不利于阅读,换行会报错,加入"+就可以解决,进行了字符串的拼接
切片类型也不可以乱写,要与序列化的切片同结构
(3)运行
D:\go project\src\go_code\chapter14\json\unmarshal>go run main.go
反序列化后 slice=map[age:7 name:Jack address:北京]
map[address:墨西哥 夏威夷 age:20 name:Tom]]
反序列完全成功
D:\go project\src\go_code\chapter14\json\unmarshal>
Slice 中包含两个切片
三、总结
对上面代码的小结
1.在反序列化一个 json 字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。(例如原来数据通过序列化 monster 结构体得到,也要反序列化 monster,如果反序列化成结构体 dog,不可以,字段会匹配失败,除非dog 中的字段与 monster 完全一样)
改变后测试(monster 变为 Dog,牛魔王后多了~~)
type Dog struct{
Name string `json: "monster_name"//反射机制
Age int `json : "monster_age"
Birthday string // ....
sal float64
skill string
}
//演示将 json 字符串,反序列化成 struct
func unmarsha1Structo {
//说明 str 在项目开发中,是通过网络传输获取到..或者是读取文件获取到
str :="("Name\": "牛魔王~~\", "Age":500, "Birthdayl":1"2011-11-111","Sal\":8000,"Skil1\":\"牛魔拳\"}"
//定义一个Monster实例
var monster Monster
err := json.Unmarshal([]byte(str),&monster)
if err != nil {
fmt.Printf("unmarshal err=%vin", err)
}
fmt.Printf("反序列化后monster=%v\n",monster,)
运行结果不受影响
D:\go project\src\go_code\chapter14\json\unmarshal>go run main.go
反序列化后monster=<牛魔王 500 2001-11-11 8000 牛魔拳>
D:\go project\src\go_code\chapter14\json\unmarshal>
2.如果 json 字符串是通过程序获取到的,则不需要再对“转义处理。因为内部已经转义。
也就是
func unmarsha1Map() {
str := "{ \"address\":\"洪崖洞", \"age\":30,\ "name\":\"红孩儿\"}"
改为
func unmarsha1Map() {
//str := "{ \"address\":\"洪崖洞", \"age\":30,\ "name\":\"红孩儿\"}"
//定义一个 ma