Golang学习(二十九)序列化和反序列化
我们不同编程语言之间的数据是无法直接交互的,我们想要解决这个问题
就需要将不同语言之间传输的数据做一个统一规范,而json是目前最流行的数据格式
一、json是什么
json 是一种数据交换格式,主要是将要传输的数据转换为json特有的格式
其他人拿到这个json数据后,可以通过数据反向转换得到转换前的数据
这样大家都将数据转为json格式,谁用就拿过来转换为自己识别的数据即可
json数据格式说明
JSON 依赖key-value 键值对形式来保存数据,而“键值对”组合中的键名
写在前面,并且用双引号""包裹,使用冒号:分隔,然后紧跟值
案例 常见格式定义
//json格式key-value
{"firstName": "Json"}//包含数组的json,value通过方括号包裹
{"address":["北京","上海"]} //存放多个json,通过逗号分割
[{"name":"tom"},{"haha":"test"}]
当我们不确定这个格式是否正确,可以找个解析的网站去查看
https://www.json.cn/
案例2 当有多个用户信息时逗号分割
[
{"name":"韩梅梅","age":20,"address":["上海","北京"]},
{"name":"李雷","age":26,"address":["山西","北京"]}
]
自动排列效果
[{"name":"韩梅梅","age":20,"address":["上海","北京"]},{"name":"李雷","age":26,"address":["山西","北京"]}
]
二、json序列化
json序列化是指,将语言中键值对类型的数据转换为json字符串
比如go语言中的结构体、map、数组、切片等,转换为json的格式被称为格式化
登陆标准库文档
https://studygolang.com/pkgdoc
有一个叫 encoding/json 的包是用于处理json字符串的
根据开篇的提示找到Marshal与Unmarshal 函数,他们是用于正反向转换json用的
func Marshal(v interface{}) ([]byte, error)//通过文档得知,Marshal函数接收的是一个空接口类型
//意思是我们可以将go的任意类型的数据传入进去
//而返回值是一个byte的切片,以及error
1 结构体序列化
package mainimport ("encoding/json""fmt"
)type Monster struct{ //我们先定义一个结构体Name stringAge intBirthady stringSal float64Skill string
}func main(){monster := Monster{ //实例化结构体Name: "牛魔王",Age: 500,Birthady: "2011-11-11",Sal: 8000.0,Skill: "牛魔拳",}data,err := json.Marshal(&monster) //通过json包下的Marshal函数对结构体进行转换if err != nil{fmt.Printf("序列化错误 err=%v",err)}//输出序列化的结果fmt.Printf("monster序列化后=%v\n",string(data))
}
返回
monster序列化后={"Name":"牛魔王","Age":500,"Birthady":"2011-11-11","Sal":8000,"Skill":"牛魔拳"}
2、map序列化
package mainimport ("encoding/json""fmt"
)func testMap(){//定义一个mapvar a map[string]interface{}a = make(map[string]interface{})a["name"] = "红孩儿"a["age"] = 30a["address"] = "火云洞"data,err := json.Marshal(a) //将a这个map进行序列化if err != nil{fmt.Printf("序列化错误 err=%v",err)}fmt.Printf("a map序列化后=%v\n",string(data))
}
func main(){testMap()
}
返回
a map序列化后={"address":"火云洞","age":30,"name":"红孩儿"}
map类型是无序的,所以结果略有不同
3、切片序列化
package mainimport ("encoding/json""fmt"
)func testSlice(){var slice []map[string]interface{} //定义一个切片,声明值为空接口var m1 map[string]interface{}m1 = make(map[string]interface{})m1["name"] = "jack"m1["age"] = "7"m1["address"] = "北京"slice = append(slice,m1) //将m1加入切片var m2 map[string]interface{}m2 = make(map[string]interface{})m2["name"] = "tom"m2["age"] = "20"m2["address"] = "墨西哥"slice = append(slice,m2) //将m2加入切片data,err := json.Marshal(slice) //将切片进行序列化操作if err != nil{fmt.Printf("序列化错误 err=%v",err)}fmt.Printf("切片序列化后=%v\n",string(data))
}
func main(){testSlice()}
返回
切片序列化后=[{"address":"北京","age":"7","name":"jack"},{"address":"墨西哥","age":"20","name":"tom"}]
我们发现他变成一个数组了,因为他里面有多个json,多个json通过逗号分隔
4、基本数据类型 序列化
基本数据类型虽然没有键值对,但是也是可以做序列化的,但是没有意义
package mainimport ("encoding/json""fmt"
)
func testFloat64(){var num1 float64 = 23456.68//序列化data,err := json.Marshal(num1)if err != nil{fmt.Printf("序列化错误 err=%v",err)}fmt.Printf("普通数据类型序列化后=%v\n",string(data))
}
func main(){testFloat64()}
5、序列化数组
package mainimport ("encoding/json""fmt"
)
func testSlice(){var slice []map[string]interface{} //定义一个切片,和上面切片类似var m1 map[string]interface{} m1 = make(map[string]interface{})m1["name"] = "jack"m1["age"] = "7"m1["address"] = "北京"slice = append(slice,m1)var m2 map[string]interface{}m2 = make(map[string]interface{})m2["name"] = "tom"m2["age"] = "20"m2["address"] = [2]string{"墨西哥","夏威夷"} //我们在某个值中定义为数组slice = append(slice,m2)data,err := json.Marshal(slice)if err != nil{fmt.Printf("序列化错误 err=%v",err)}fmt.Printf("切片序列化后=%v\n",string(data))
}
func main(){testSlice()}
返回
切片序列化后=[{"address":"北京","age":"7","name":"jack"},{"address":["墨西哥","夏威夷"],"age":"20","name":"tom"}]
三、标签
我们上面序列化结构体的时候,实际上就是把字段的key作为json的key使用
但在浏览器中我们更希望接收到的是首字母小写的字段,为了不破坏结构体调用,使用标签
package mainimport ("encoding/json""fmt"
)
//定义一个结构体
type Monster struct{Name string `json:"xxx_name"` //我们在定义结构体的时候,设置好tag json的一个标签Age int `json:"xxx_age"` //这样在转换时,就会转换为小写Birthady stringSal float64Skill string
}func testStruct(){monster := Monster{Name: "牛魔王" ,Age: 500,Birthady: "2011-11-11",Sal: 8000.0,Skill: "牛魔拳",}data,err := json.Marshal(&monster)if err != nil{fmt.Printf("序列化错误 err=%v",err)}fmt.Printf("monster序列化后=%v\n",string(data))
}func main(){testStruct()}
返回
monster序列化后={"xxx_name":"牛魔王","xxx_age":500,"Birthady":"2011-11-11","Sal":8000,"Skill":"牛魔拳"}
我们在结构体后面添加别名,这样在序列化时导出的就是别名的字段了
我们不能直接将字段定义为小写,这样会影响到其他的包进行调用
四、反序列化
就是将我们上面转换的json,重新转换为我们go所使用的数据类型
func Unmarshal(data []byte, v interface{}) error//传入的值是一个切片类型
//后面的v interface是指定我们用于接收json数据的结构体
//是否接收成功返回一个error的值
1、json转换为结构体
package mainimport ("encoding/json""fmt"
)
//定义一个结构体,必须要有这个结构体才能去反序列化到结构体
type Monster struct{Name stringAge intBirthady stringSal float64Skill string
}func unmarshalStruct(){//我们将这个json写入到变量,不过因为他本身有双引号,这里通过反斜杠将双斜杠转义//在实际开发中,这个str的字符串是通过前端POST上传或者读取文件得到的str := "{\"Name\":\"牛魔王\",\"Age\":500,\"Birthady\":\"2011-11-11\",\"Sal\":8000,\"Skill\":\"牛魔拳\"}"var monster Monster //定义一个结构体,去接收反序列化json的结果err := json.Unmarshal([]byte(str),&monster) //反序列化,通过[]byte(str)类型断言将str转换为切片if err != nil{fmt.Printf("unmarshal err=%v\n",err)}fmt.Printf("反序列化后 monster=%v",monster)
}func main(){unmarshalStruct()
}
返回
反序列化后 monster={牛魔王 500 2011-11-11 8000 牛魔拳}
2、json转换为map
package mainimport ("encoding/json""fmt"
)
func unmarshalMap(){str := "{\"address\":\"火云洞\",\"age\":30,\"name\":\"红孩儿\"}"var a map[string]interface{} //定义一个map,必须和要转换的json之前的数据类型相同//反序列化时,Unmarshal已经封装了make动作,这里就不make了err := json.Unmarshal([]byte(str),&a) //反序列化,必须传入&a才可使用if err != nil{fmt.Printf("unmarshal err=%v\n",err)}fmt.Printf("反序列化map后 a=%v",a)
}func main(){unmarshalMap()
}
返回
反序列化map后 a=map[address:火云洞 age:30 name:红孩儿]
3、json反序列化成切片
package mainimport ("encoding/json""fmt"
)
func unmarshalSclice(){str := "[{\"address\":\"北京\",\"age\":\"7\",\"name\":\"jack\"}," +"{\"address\":\"墨西哥\",\"age\":\"20\",\"name\":\"tom\"}]"var slice []map[string]interface{} //定义一个切片,同样无需序列化err := json.Unmarshal([]byte(str),&slice)if err != nil{fmt.Printf("unmarshal err=%v\n",err)}fmt.Printf("反序列化slice后 slice=%v",slice)
}
func main(){unmarshalSclice()
}
返回
反序列化slice后 slice=[map[address:北京 age:7 name:jack] map[address:墨西哥 age:20 name:tom]]
小结说明
1、在反序列化一个json串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致
2、上面的str是为了测试,在实际中是通过其他程序return过来,或者tcp传输过来的,不需要反斜杠去转义双引号
Golang学习(二十九)序列化和反序列化相关推荐
- Java多线程学习二十九:AtomicInteger(原子类) 和 synchronized 的异同点?
原子类和 synchronized 关键字都可以用来保证线程安全,在本课时中,我们首先分别用原子类和 synchronized 关键字来解决一个经典的线程安全问题,给出具体的代码对比,然后再分析它们背 ...
- Golang学习(二十四)家庭记账项目
一.项目开发流程 需求分析-->设计阶段-->实现阶段(代码)-->测试阶段-->实施阶段-->维护阶段 二.项目需求说明 1.模拟实现基于文本界面的 <家庭记账软 ...
- Golang 学习二十五(UDP 编程)
文章目录 1. 服务端配置 2. 客户端配置 3. 实现双向聊天 4. 优化多客户端实现通讯 UDP 是用户数据报协议,是一种无连接传输协议,不需要建立连接就可以直接发送和接收数据,属于不可靠的,没有 ...
- ballerina 学习二十九 数据库操作
ballerina 数据操作也是比较方便的,官方也我们提供了数据操作的抽象,但是我们还是依赖数据库驱动的. 数据库驱动还是jdbc模式的 项目准备 项目结构 ├── mysql_demo │ ├── ...
- python学习 (二十九) range函数
1:list函数可以将其他类型转成list. print(list(range(0, 10))) 2: list函数把元组转成list t = (1, 3, 3, 5) print(list(t)) ...
- OpenGL学习二十九:模板缓冲区与模板测试
帧缓冲区有许多缓冲区构成,这些缓冲区大致分为: 颜色缓冲区:用于绘图的缓冲区,它包含了颜色索引或者RGBA颜色数据. 深度缓冲区:存储每个像素的深度值,当启动深度测试时,片段像素深度值和深度缓冲区深度 ...
- 风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识
风炫安全Web安全学习第三十九节课 反序列化漏洞基础知识 反序列化漏洞 0x01 序列化相关基础知识 0x01 01 序列化演示 序列化就是把本来不能直接存储的数据转换成可存储的数据,并且不会丢掉数据 ...
- JavaScript学习(二十九)—JS常用的事件
JavaScript学习(二十九)-JS常用的事件 一.页面相关事件 onload事件:当页面中所有的标签都加载完成后厨房该事件,格式:window.onload <body><sc ...
- Socket通信学习(二):序列化与反序列化
Socket通信学习(二):序列化与反序列化 HoloLens的开发最近需要用到Socket通信,所以创建本系列进行记录,欢迎大家批评指正! 前言 Socket通信的默认发送的数据为byte[]类型, ...
最新文章
- TextView-- 测量文字宽度
- 瑞士电信vCPE商用落地 华三通信NFV方案成最大功臣
- guava和commons_使用Guava CharMatcher和Apache Commons Lang StringUtils确定字符串中字符或整数的存在...
- putil:一个用于获得处理器和系统相关信息的模块
- arch linux 树莓派,树莓派上安装配置Archlinux
- Android Studio 使用笔记:快捷键
- C#网站发布在IIS10上,Access数据库读取为空白的解决方案
- 16QAM matlab/simulink仿真
- 关于gotoxy函数
- scrapy中文文档基础知识
- 安装SQL 2000 企业版
- 动态代理的中介出租房屋
- CentOS下常用软件开机自启动脚本
- 一键式统计6.0季报测试
- 《Fundamentals of Computer Grahpics》虎书第三版翻译——第四章 光线追踪
- 面向对象:对象的概念
- 针对chromium IME的外接输入法框架
- Shader实现喷射蜘蛛网特效
- Win10连接Bose QC30 显示已配对但连接失败
- 2018年计算机考研真题及参考答案
热门文章
- 软件需求与软件需求规约
- Error (10267)
- SEO 网站排名优化(资源收藏,用得着时看看)
- android 打包aar,和引入aar
- 详解体温枪研发到生产出售需要的资质认证流程
- Educational Codeforces Round 67 (Rated for Div. 2)(D思维题 线段树/E树形dp(换根dp) 二次扫描与换根法)
- 什么是SFTP,看这篇就够了 ^^
- one morning of Saturday
- Spark中dataframe里data.drop()和data.na.drop()的区别
- 与程序猿谈恋爱后,我不得不做心机婊