JSON (JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成。尽管JSON是JavaScript的一个子集,但JSON采用完全独立于编程语言的文本格式,且表现为键/值对集合的文本描述形式(类似一些编程语言中的字典结构),这使它成为较为理想的、跨平台、跨语言的数据交换语言。
例如:
{
"Company": "itcast",
"Subjects": [
"Go",
"C++",
"Python",
"Test"
],
"IsOk": true,
"Price": 666.666
}
开发者可以用 JSON 传输简单的字符串、数字、布尔值,也可以传输一个数组,或者一个更复杂的复合结构。在 Web 开发领域中, JSON被广泛应用于 Web 服务端程序和客户端之间的数据通信。
json.MarshalIndent(m, "", " ")json.Unmarshal([]byte(jsonBuf), &tmp)
对于struct tag
我们看到上面的输出字段名的首字母都是大写的,如果你想用小写的首字母怎么办呢?把结构体的字段名改成首字母小写的?JSON输出的时候必须注意,只有导出的字段(首字母是大写)才会被输出,如果修改字段名,那么就会发现什么都不会输出,所以必须通过struct tag定义来实现。
针对JSON的输出,我们在定义struct tag的时候需要注意的几点是:
- 字段的tag是"-",那么这个字段不会输出到JSON
- tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中
- tag中如果带有"omitempty"选项,那么如果该字段值为空,就不会输出到JSON串中
- 如果字段类型是bool, string, int, int64等,而tag中带有",string"选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串
type IT struct {
// 成员变量名首字母必须大写
Company string
Subjects []string
IsOk bool
Price float64
}
// 如果要对成员变量进行大小写等的修改,不能直接进行修改,而是要进行二次编码
type IT struct {
Company string `json:"-"` // - 表示该行不会输出到屏幕上
Subjects []string `json:"Subjects"` // 这样就会把Subjects编程小写subjects了
IsOk bool `json:",string"` // 将变量变成字符串的形式输出,注意,和string之间不能有空格
Price float64 `json:",string"` // 将变量变成字符串的形式输出,注意,和string之间不能有空格
}
JSON的生成
1. 通过结构体生成json
type IT struct {
// 成员变量名首字母必须大写
Company string `json:"company"`
Subjects []string `json:"subjects"`
IsOk bool `json:"is_ok"`
Price float64 `json:"price"`
}
func test1() {
s := IT{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.666}
//buf, err := json.Marshal(s) // 编码,根据内容生成json文本
// json.Marshal(s) 执行后: {"Company":"itcast","Subjects":["Go","C++","Python","Test"],"IsOk":true,"Price":666.666}
buf, err := json.MarshalIndent(s, "", " ") // 格式化编码
// json.MarshalIndex 执行后:
//{
//"Company": "itcast",
//"Subjects": [
// "Go",
// "C++",
// "Python",
// "Test"
//],
//"IsOk": true,
//"Price": 666.666
//}
if err != nil {
fmt.Println("err = ", err)
return
} else {
fmt.Println("buf = ", string(buf))
}
}
2.通过map生成json
func test2() {
// 创建一个map
m := make(map[string]interface{}, 4)
m["company"] = "itcast"
m["subjects"] = []string{"Go", "C++", "Python", "Test"}
m["isok"] = true
m["price"] = 666.666
// 编码成json
res, err := json.MarshalIndent(m, "", " ")
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("res = ", string(res))
}
JSON的解析
如果要将json解析出来进行处理,推荐使用结构体,因为map获取每一个json字段进行处理的逻辑比较麻烦。
1. JSON解析到结构体
type IT struct {
// 成员变量名首字母必须大写
Company string `json:"company"`
Subjects []string `json:"subjects"`
IsOk bool `json:"is_ok"`
Price float64 `json:"price"`
}
func test3() {
jsonBuf := `
{
"Company":"itcast",
"Subjects":[
"Go",
"C++",
"Python",
"Test"
],
"IsOk":true,
"Price":666.666
}
`
var tmp IT // 定义一个结构体变量
err := json.Unmarshal([]byte(jsonBuf), &tmp)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Printf("tmp = %+v\n", tmp)
// 如果只打印一个json信息,例如只打印subjects,那就在定义结构体变量的时候,只定义一个subjects
type IT2 struct {
Subjects []string `json:"subjects"`
}
var tmp2 IT2 // 定义一个结构体变量
err2 := json.Unmarshal([]byte(jsonBuf), &tmp2)
if err2 != nil {
fmt.Println("err2 = ", err2)
return
}
fmt.Printf("tmp2 = %+v\n", tmp2)
}
2. JSON解析到map
func test4() {
jsonBuf := `
{
"Company":"itcast",
"Subjects":[
"Go",
"C++",
"Python",
"Test"
],
"IsOk":true,
"Price":666.666
}
`
// 创建一个map
m := make(map[string]interface{}, 4)
err := json.Unmarshal([]byte(jsonBuf), &m)
if err != nil {
fmt.Println("err = ", err)
return
}
// 普通打印
fmt.Printf("m = %+v\n", m)
// 通过类型断言,反推找到某个字段与对应内容
var str string
for key, value := range m {
switch data := value.(type) {
case string:
str = data // 验证是否可以赋值 ————> 可以
fmt.Printf("map[%s] 类型为string,内容 = %s\n", key, str)
case float64:
fmt.Printf("map[%s] 类型为float64,内容 = %f\n", key, data)
case bool:
fmt.Printf("map[%s] 类型为bool,内容 = %v\n", key, data)
case []interface{}:
fmt.Printf("map[%s] 类型为[]string,内容 = %v\n", key, data)
}
}
}