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)
		}
	}
}