JSON处理
# 1,编码 json
JSON(JavaScript Object Notation)是一种比 XML 更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成。尽管 JSON 是 JavaScript 的一个子集,但 JSON 采用完全独立于编程语言的文本格式,且表现为键/值对
集合的文本描述形式(类似一些编程语言中的字典结构),这使它成为较为理想的,跨平台,跨语言的数据交换语言。
{
"Company": "itcast",
"Subjects": ["Go", "C++", "Python", "Test"],
"Isok": true,
"Price": 666
}
2
3
4
5
6
开发者可以用 JSON 传输简单的字符串,数字,布尔值,也可以传输一个数组,或者一个更复杂的复合结构。在 web 开发领域中,JSON 被广泛应用于 web 服务端程序和客户端之间的数据通信。
Go 语言内建对 JSON 的支持。使用 Go 语言内置的encoding/json
标准库,开发者可以轻松使用 Go 程序生成和解析 JSON 格式的数据。
JSON 官方网站:http://www.json.org 在线格式化:http://www.json.cn
# 1,通过结构体生成 JSON
使用 json.Marshal()函数可以对一组数据进行 JSON 格式的编码。 json.Marshal()函数的声明如下:
func Marshal(v interface{}) ([]byte, error)
还有一个格式化输出:
// MarshalIndent 很像 Marshal,只是用缩进对输出进行格式化
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
2
# 1,示例代码
package main
import (
"encoding/json"
"fmt"
)
/*
{
"Company":"itcast",
"Subjects":[
"Go",
"C++",
"Python",
"Test"
],
"Isok":true,
"Price":666.66
}
*/
type It struct {
Company string //注意变量名称必须是大写开头
Subjects []string
Isok bool
Price float64
}
func main() {
//定义一个结构体变量,同时初始化
s := It{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.66}
//根据内容生成json文本的过程,叫编码
//通过json文本解析成内容的过程,叫解码
//buf, err := json.Marshal(s)
//以上定义方式输出结果: buf = {"Company":"itcast","Subjects":["Go","C++","Python","Test"],"Isok":true,"Price":666.66}
buf, err := json.MarshalIndent(s, "", " ") //格式化编码
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("buf = ", string(buf))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
输出结果:
$ go run 11_通过结构体生成json.go
buf = {
"Company": "itcast",
"Subjects": [
"Go",
"C++",
"Python",
"Test"
],
"Isok": true,
"Price": 666.66
}
2
3
4
5
6
7
8
9
10
11
12
# 2,几个技巧。
我们看到上面的输出字段名的首字母都是大写的,如果你想用小写的首字母怎么办呢?把结构体的字段名改成首字母小写的?JSON 输出的时候必须注意,只有导出的字段(首字母是大写)才会被输出,如果修改字段名,那么就会发现什么都不会输出,所以必须通过 struct tag 定义来实现。
针对 JSON 的输出,我们在定义 struct tag 的时候需要注意的几点是:
- 字段的 tag 是”-“,那么这个字段不会输出到 JSON
- tag 中带有自定义名称,那么这个自定义名称会出现在 JSON 的字段名中
- tag 中如果带有”omitempty”选项,那么如果该字段值为空,就不会输出到 JSON 串中
- 如果字段类型是 bool, string, int, int64 等,而 tag 中带有”,string”选项,那么这个字段在输出到 JSON 的时候会把该字段对应的值转换成 JSON 字符串
package main
import (
"encoding/json"
"fmt"
)
type It struct {
Company string `json:"company"` //二次编码,可以将变量名称转为小写
Subjects []string `json:"-"` //表示这个字段不会输出打印
Isok bool `json:",string"` //表示先转换为字符串,再输出到屏幕
Price float64 `json:"price, omitempty"` //如果Price为空,则不输出到json串当中
}
func main() {
//定义一个结构体变量,同时初始化
s := It{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.66}
//根据内容生成json文本的过程,叫编码
//通过json文本解析成内容的过程,叫解码
//buf, err := json.Marshal(s)
//以上定义方式输出结果: buf = {"Company":"itcast","Subjects":["Go","C++","Python","Test"],"Isok":true,"Price":666.66}
buf, err := json.MarshalIndent(s, "", " ") //格式化编码
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("buf = ", string(buf))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
输出结果:
$ go run 11_通过结构体生成json.go
buf = {
"company": "itcast",
"Isok": "true",
"Price": "666.66"
}
2
3
4
5
6
# 2,通过 map 生成 json。
package main
import (
"encoding/json"
"fmt"
)
func main() {
//创建一个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
//result, err := json.Marshal(m)
result, err := json.MarshalIndent(m, "", " ")
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("result = ", string(result))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 2,解码 json
可以使用 json.Unmarshal()函数将 JSON 格式的文本解码为 Go 里面预期的数据结构。
json.Unmarshal()函数的原型如下:
func Unmarshal(data []byte, v interface{}) error
该函数的第一个参数是输入,即 JSON 格式的文本(比特序列),第二个参数表示目标输出容器,用于存放解码后的值。
# 1,json 解析为结构体。
package main
import (
"encoding/json"
"fmt"
)
type It struct {
Company string `json:"company"`
Subjects []string `json:"subjects"`
Isok bool `json:"isok"`
Price float64 `json:"price"`
}
func main() {
jsonbuf := `
{
"company": "itcast",
"subjects": [
"Go",
"C++",
"Python",
"Test"
],
"isok": true,
"price": 666.66
}`
var tmp It
err := json.Unmarshal([]byte(jsonbuf), &tmp)
if err != nil {
fmt.Println("err = ", err)
return
}
//fmt.Println("tmp = ", tmp)
fmt.Printf("tmp = %+v\n", tmp) //以详细格式输出
//如果不想要某些字段输出,那么只需要在定义结构体的时候略掉即可
type It1 struct {
Subjects []string `json:"subjects"`
}
var tmp1 It1
err = json.Unmarshal([]byte(jsonbuf), &tmp1)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Printf("tmp1 = %+v\n", tmp1) //以详细格式输出
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 2,json 解析为 map。
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonbuf := `
{
"company": "itcast",
"subjects": [
"Go",
"C++",
"Python",
"Test"
],
"isok": true,
"price": 666.66
}`
//创建一个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
// str = string(m["company"])
// fmt.Println("str = ", str) //err,无法转换类型
//类型断言
for key, value := range m {
switch data := value.(type) {
case string:
fmt.Printf("map[%s]的类型为string,value = %s\n", key, data)
case bool:
fmt.Printf("map[%s]的类型为bool,value = %v\n", key, data)
case float64:
fmt.Printf("map[%s]的类型为float64,value = %v\n", key, data)
// case []string:
// fmt.Printf("map[%s]的类型为[]string,value = %v\n", key, data) //不会打印结果
case []interface{}:
fmt.Printf("map[%s]的类型为[]interface{},value = %v\n", key, data) //接着还可以对其进行迭代打印
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
运行结果:
$ go run 14_json解析成map.go
m = map[company:itcast subjects:[Go C++ Python Test] isok:true price:666.66]
map[company]的类型为string,value = itcast
map[subjects]的类型为[]interface{},value = [Go C++ Python Test]
map[isok]的类型为bool,value = true
map[price]的类型为float64,value = 666.66
2
3
4
5
6