75142913在线留言
GO语言学习笔记10:各种数据类型通过Marshal和Unmarshal对JSON序列化与反序列化_Go语言_网络人

GO语言学习笔记10:各种数据类型通过Marshal和Unmarshal对JSON序列化与反序列化

Kwok 发表于:2020-10-10 09:10:09 点击:12 评论: 0

做过数据交换或者前端开发的小伙伴们肯定对json不陌生,这里就不长篇大论的介绍JSON,做为一个轻量级的数据交换格式并易于人类的阅读和编写,让JSON在现在的H5、网站开发、APP、小程序等地方大放异彩~目前已成为主流的数据格式,GO语言提供了json.Marshal对结构体、map、切片、数组等数据类型序列化(转为json格式)操作,也提供了一个json.Unmarshaljson转回相应的数据类型。

在GO语言的源代码里可以看到是传入一个空接口,在http://www.neter8.com/go/79.html 有介绍,任何的数据类型都实现了一个空接口,所以marshal可以把任何的数据类型json序列化:

func Marshal(v interface{}) ([]byte, error)//GO源代码:传入一个空接口对象,返回一个byte切片和一个错误(无错返回nil)
func Unmarshal(data []byte, v interface{}) error//传入一个数据的byte切片,和一个空接口,返回错误(无错返回nil)

一、对数组序列化和反序列化操作

因为数组是0~n的方式索引,所以序列化为没有key只有value,一般用处不大,这里做为一个知识点了解即可,数组的特点:http://www.neter8.com/go/73.html

var array = [3]string{"张三", "李四", "王五"}
data, err := json.Marshal(array)
if err != nil {
	fmt.Println("Json序列化出错,原因:", err)
} else {
	fmt.Println(data)         //直接打印出来是一个byte切片:[91 34 229 188 160 228 ...]
	fmt.Println(string(data)) //将切片转为string后正常显示["张三","李四","王五"]
}

//下面把json转回为数组,为了和上面区别增加了“赵六”
var str string = "["张三","李四","王五","赵六"]"
var array2 [4]string                       //定义一个数组接收反序列化后的json
err = json.Unmarshal([]byte(str), &array2) //将str 转为byte切片传参,&array2为指针传参(因为只返回错误,不传指针就不能修改array2)
if err != nil {
	fmt.Println("Json反序列化出错,原因:", err)
} else {
	fmt.Println(array2) //[张三 李四 王五 赵六]
}

二、结构体序列化与反序列化

结构体可以存多种数据类型,所以在实战中最实用也最常用,而且还提供了tag标签重命名key值,了解结构体:http://www.neter8.com/go/78.html

//带有tag的结构体
type student struct {
	Name  string `json:"名字"` //tag标签是反射机制
	Age   int    `json:"nianji"`
	Class string //没有tag标签将直接使用变量做为val
}

//不带tag的结构体用于接收
type student2 struct {
	Name  string
	Age   int
	Class string
}

func main() {
	var stu = student{"张三", 15, "9年级3班"}
	data, err := json.Marshal(stu)
	if err != nil {
		fmt.Println("Json序列化出错,原因:", err)
	} else {
		fmt.Println(string(data)) //{"名字":"张三","nianji":15,"Class":"9年级3班"}
		/*可以看到通过TAG标签我们可以使用中文做为val,反正就是可以自己定义val名字呢~*/
	}

	//将JSON转为结构体数据
	//结构体里变量首字母大写,json小写不会造成影响,不区别大小写,但变量名字要一致
	str := "{"name":"张三","age":15,"class":"9年级3班"}"
	var stu2 student2                       //实例化一个student2结构体接收反序列化
	err = json.Unmarshal([]byte(str), &stu2) //将string转为byte切片,接收结构体需要传入指针,否则会报:call of Unmarshal passes non-pointer as second argument
	if err != nil {
		fmt.Println("Json反序列化出错,原因:", err)
	} else {
		fmt.Println(stu2, stu2.Name) //{张三 15 9年级3班} 张三
	}
}

结构带有tag标签虽然能不出错的转换数据,但是会出现数据丢失的情况。所以在实际开发中,tag尽量只改大小写即可,上面是一个不好的演示,只说明可以实现的方式,请在实战中使用规范的命名方式!

三、map的序列化与反序列化

map序列化和上面基本一样,只需要注意遵守map数据类型的特点就好了,Unmarshal会对map与切片进行类型断言并自动make。

//定义一个map并赋值,自动make空间
var stuMap = map[string]string{"name": "张三", "age": "15", "class": "9年级3班"}
data, err := json.Marshal(stuMap)
if err == nil {
	fmt.Println(string(data)) //{"age":"15","class":"9年级3班","name":"张三"}
}
//将JSON转为map
//json数据要和map的一样[string]string,全部需要“"”引起来,否则会失败json: cannot unmarshal number into Go value of type string
str := "{"name":"张三","age":15,"class":"9年级3班"}"
var stu2 map[string]string//定义一个map,数据类型要与json过来的一致,不需要make就可以使用!
err = json.Unmarshal([]byte(str), &stu2) //map不需要make后使用,Unmarshal内部已完成了这一步的封装
if err == nil {
	fmt.Println(stu2) //map[age:15 class:9年级3班 name:张三]
}

map解析成json的时候,key必须只能是string,这是json语法要求的。

四、切片的序列化与反序列化

切片使用和map一样,不需要make就能使用。关于切片的详细解析: http://www.neter8.com/go/74.html

var stuSlice = [][]string{{"张三", "15", "9年级3班"}, {"李四", "16", "9年级1班"}}
data, err := json.Marshal(stuSlice)
if err == nil {
	fmt.Println(string(data)) //[["张三","15","9年级3班"],["李四","16","9年级1班"]]
}

//切片反序列化
str := "[{"name":"张三","age":"15","class":"9年级3班"},{"name":"李四","age":"16","class":"9年级1班"}]"

//定义一个切片格式与json要有所对应,var stu2 []map[string]interface{}最后的值interface{}可以是任何类型
var stu2 []map[string]string
err = json.Unmarshal([]byte(str), &stu2)
if err == nil {
	fmt.Println(stu2) //[map[age:15 class:9年级3班 name:张三] map[age:16 class:9年级1班 name:李四]]
}

上面是已知json数据结构的解析方式,如果json结构是未知的或者结构可能会发生改变的情况,则解析到struct是不合理的。这时可以解析到空接口interface{}或map[string]interface{}类型上,这两种类型的结果是完全一致的。

数组与切片等json转回类型的时候一定要保证前后的数据一致性,如果json存在于变量里的时候是不需要使用转义的。

除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:http://www.neter8.com/go/82.html
标签:jsonGOmarshalKwok最后编辑于:2020-10-10 13:10:44
0
感谢打赏!

《GO语言学习笔记10:各种数据类型通过Marshal和Unmarshal对JSON序列化与反序列化》的网友评论(0)

本站推荐阅读

热门点击文章