golang 语言标准库 encoding/json
结构体slice 转 JSON 叫编组
编码时 , 通过反射技术 , 只有导出(首字母大写)的成员才会被编码
通道、复数、函数类型的值不能编码进json。
json.Marshal 编码
返回没有空格的紧凑字节数组
1
|
data, err := json.Marshal(movies)
|
json.MarshalIndent 格式化编码
返回包含空格的格式化字节数组
参数 2 : 每一行的输出前缀
参数 3 : 层级缩进
1
|
data, err := json.MarshalIndent(movies, "", " ")
|
**Unmarshal ** 解码
首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。
1
2
3
4
|
var titles []struct{ Title string }
if err := json.Unmarshal(data, &titles); err != nil {
log.Fatalf("JSON unmarshaling failed: %s", err)
}
|
结构体中只有Title成员。通过定义合适的Go语言数据结构,我们可以选择性地解码JSON中感兴趣的成员。
Decoder 流解码器
还有 Encoder 流编码器
1
2
3
4
5
6
7
8
9
10
11
12
|
type IssuesSearchResult struct {
TotalCount int `json:"total_count"`
Items []*Issue
}
var result IssuesSearchResult
// 发起网络请求, 拿到 resp.body
// 此处对流解码 , 也可以使用 ioutil.ReadALL 来读取流数据
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
resp.Body.Close()
return nil, err
}
|
tag
Tag可以是任意的字符串面值 , 通常是一系列用空格分隔的key:“value"键值对序列;
json开头键名对应的值用于控制encoding/json包的编码和解码的行为
json:"color"
编码后的名字为 color
json:",omitempty"
名字为变量名, 该类型若为零值 或 nil, 不会被编码
json:"-"
忽略, 不会被编码
json:",string"
编码时为字符串, 仅适用于变量为 字符串、浮点数、整数类型的字段
omitempty :
1
2
3
4
|
type movies struct{
Year int `json:"released"`
Color bool `json:"color,omitempty"`
}
|
匿名结构体编码
1
2
3
4
5
6
7
8
9
|
type Page struct {
Color int
Size int
}
type Book struct {
Page
Size int
}
|
- book 中 Size 与 page 中 Size 命名冲突, page 的 Size 不会被编码
- 编码后
{"Color":255,"Size":12}
对特殊字符转义操作 url.QueryEscape
在 URL 中加入查询参数, 避免 ? &
等歧义 , 可以先使用 url.QueryEscape 转义
1
2
|
q := url.QueryEscape(strings.Join(terms, " "))
resp, err := http.Get(IssuesURL + "?q=" + q)
|
Json反序列化数字到interface{}类型的值中,默认解析为float64类型,在使用时要注意。
1
2
3
4
5
6
7
8
9
10
11
|
var data = []byte(`{"status": 200}`)
var result map[string]interface{}
if err := json.Unmarshal(data, &result); err != nil {
fmt.Println("error:", err)
return
}
//var status = result["status"].(int) //error: panic: interface conversion: interface is float64, not int
var status = uint64(result["status"].(float64)) //ok
fmt.Println("status value:",status)
|