目录【阅读时间:约5分钟】
一.概述
1.Json的作用
Json(Javascript Object Nanotation)是一种数据交换格式,常用于前后端数据传输。任意一端将数据转换成json 字符串,另一端再将该字符串解析成相应的数据结构,如string类型,strcut对象等。
2.Go官方 encoding/json 包
Go官方 encoding/json 包 实现了 RFC 4627 中定义的 JSON 的编码和解码。JSON 和 Go值之间的映射在 Marshal 和 Unmarshal 函数的文档中进行了描述。
官方源码:https://github.com/golang/go/blob/master/src/encoding/json/encode.go
3. golang json的主要操作
根据上面两节的介绍,我们简单可以将golang json的主要操作分为以下两种:
①Json Marshal:将数据编码成json字符串
②Json Unmarshal:将json字符串解码到相应的数据结构
使用这两种json操作,可以极大地方便前后端的数据传输操作。
二.Json Marshal:将数据编码成json字符串
Marshal函数的作用结果很直观,就是将输入的结构化数据,转为json字符流并输出。
我们可以自定义输入的数据类型以及相应的值,并将其转为符合规则的json字符流。
简单的使用样例如下(别忘了"import encoding/json"
):
type Stu struct {
Name string `json:"name"`
Age int
HIgh bool
sex string
Class *Class `json:"class"`
}
type Class struct {
Name string
Grade int
}
func main() {
//实例化一个数据结构,用于生成json字符串
stu := Stu{
Name: "张三",
Age: 18,
HIgh: true,
sex: "男",
}
//指针变量
cla := new(Class)
cla.Name = "1班"
cla.Grade = 3
stu.Class=cla
//Marshal失败时err!=nil
jsonStu, err := json.Marshal(stu)
if err != nil {
fmt.Println("生成json字符串错误")
}
//jsonStu是[]byte类型,转化成string类型便于查看
fmt.Println(string(jsonStu))
}
运行结果:
{"name":"张三","Age":18,"HIgh":true,"class":{"Name":"1班","Grade":3}}
由此可知程序包有如下几个特性:
①结构化数据转为json字符流
②支持字段的标签(Tag),标签满足 json:“你自己的定义”。
③指针变量编码时自动转换为它所指向的值
三.Json Unmarshal:将json字符串解码到相应的数据结构
Unmarshal函数的作用结果也很直观,就是将输入的json字符流,转为相应的结构化数据并输出。
Unmarshal函数可以看作是Marshal函数的逆过程,用于json的解码。
同样地,展示简单的使用样例如下(别忘了"import encoding/json"
):
type StuRead struct {
Name interface{} `json:"name"`
Age interface{}
HIgh interface{}
sex interface{}
Class interface{} `json:"class"`
Test interface{}
}
type Class struct {
Name string
Grade int
}
func main() {
//json字符中的"引号,需用\进行转义,否则编译出错
//json字符串沿用上面的结果,但对key进行了大小的修改,并添加了sex数据
data:="{\"name\":\"张三\",\"Age\":18,\"high\":true,\"sex\":\"男\",\"CLASS\":{\"naME\":\"1班\",\"GradE\":3}}"
str:=[]byte(data)
//1.Unmarshal的第一个参数是json字符串,第二个参数是接受json解析的数据结构。
//第二个参数必须是指针,否则无法接收解析的数据,如stu仍为空对象StuRead{}
//2.可以直接stu:=new(StuRead),此时的stu自身就是指针
stu:=StuRead{}
err:=json.Unmarshal(str,&stu)
//解析失败会报错,如json字符串格式不对,缺"号,缺}等。
if err!=nil{
fmt.Println(err)
}
fmt.Println(stu)
}
运行结果:
{张三 18 true <nil> map[naME:1班 GradE:3] <nil>}
四.myJsonMarshal程序包开发的踩坑经历
基于Go官方 encoding/json 包,笔者简单地复现了其中的Marshal函数,详情可见基于Golang的对象序列化的程序包开发——myJsonMarshal。
1.go doc的第一个坑——函数名首字母要大写
在进行go doc输出API文档时,笔者发现有些函数一直都无法自动生成API、有些函数能生成API的“诡异现象”,网上搜索也无相关的资料(吐槽一下go doc的资料也太少了吧!)
经过笔者的不断尝试,才发现原来是自己函数风格的问题,在go doc中,如果要通过以下命令生成API文档:
godoc -url="pkg/github.com/user/myJsonMarshal" > API.html
那么,函数名首字母必须要大写。当然我们也可以通过以下指令使API文档强制输出首字母非大写的函数:
godoc -u
当这种方法并不能生成API文档,只能在终端上显示有哪些函数,并且以下指令都是会报错的:
godoc -u -url="pkg/github.com/user/myJsonMarshal" > API.html
godoc -url="pkg/github.com/user/myJsonMarshal" > API.html -u
因此,我们还是老老实实地养成函数名首字母大写的习惯吧~
2.go doc的第二个坑——函数注释要在函数定义前一行,并且注释开头应为函数名
在写完函数注释后,笔者发现通过go doc生成的API文档居然没有显示相应的中文注释,一开始笔者以为是语言支持等问题而盲目捣鼓了不短的时间,后来才发现go doc自动生成注释时,其函数注释要在函数定义前一行,并且注释开头应为函数名。
注释格式举例:
//A 是一个样例函数
func A {
//code
}