回到简体

This commit is contained in:
chai2010
2016-02-15 11:06:34 +08:00
parent 9e878f9944
commit 2b37b23285
177 changed files with 2354 additions and 2354 deletions

View File

@@ -1,14 +1,14 @@
## 4.5. JSON
JavaScript象表示法JSON是一種用於發送和接收結構化信息的標準協議。在似的協議JSON不是唯一的一個標準協議。 XML§7.14、ASN.1和Google的Protocol Buffers都是似的協議,併且有各自的特色,但是由於簡潔性、可性和流行程度等原因JSON是用最泛的一
JavaScript象表示法JSON是一种用于发送和接收结构化信息的标准协议。在似的协议JSON不是唯一的一个标准协议。 XML§7.14、ASN.1和Google的Protocol Buffers都是似的协议,并且有各自的特色,但是由于简洁性、可性和流行程度等原因JSON是用最广泛的一
Go語言對於這些標準格式的編碼和解都有良好的支持,由標準庫中的encoding/json、encoding/xml、encoding/asn1等包提供支持譯註Protocol Buffers的支持由 github.com/golang/protobuf 包提供),併且這類包都有着相似的API接口。本,我們將對重要的encoding/json包的用法做概述。
Go语言对于这些标准格式的编码和解都有良好的支持,由标准库中的encoding/json、encoding/xml、encoding/asn1等包提供支持译注Protocol Buffers的支持由 github.com/golang/protobuf 包提供),并且这类包都有着相似的API接口。本,我们将对重要的encoding/json包的用法做概述。
JSON是JavaScript中各種類型的值——字符串、字、布值和象——Unicode本文編碼。它可以用有效可的方式表示第三章的基礎數據類型和本章的數組、slice、結構體和map等聚合數據類型。
JSON是JavaScript中各种类型的值——字符串、字、布值和象——Unicode本文编码。它可以用有效可的方式表示第三章的基础数据类型和本章的数组、slice、结构体和map等聚合数据类型。
基本的JSON型有字(十進製或科學記數法)、布true或false、字符串其中字符串是以雙引號包含的Unicode字符序列支持和Go語言類似的反斜槓轉義特性,不JSON使用的是\Uhhhh轉義數字來表示一UTF-16編碼(譯註UTF-16和UTF-8一是一種變長的編碼有些Unicode碼點較大的字符需要用4個字節表示而且UTF-16有大端和小端的問題而不是Go言的rune型。
基本的JSON型有字(十进制或科学记数法)、布true或false、字符串其中字符串是以双引号包含的Unicode字符序列支持和Go语言类似的反斜杠转义特性,不JSON使用的是\Uhhhh转义数字来表示一UTF-16编码(译注UTF-16和UTF-8一是一种变长的编码有些Unicode码点较大的字符需要用4个字节表示而且UTF-16有大端和小端的问题而不是Go言的rune型。
些基礎類型可以通JSON的數組和對象類型進行遞歸組合。一JSON數組是一有序的值序列,在一方括號中併以逗分隔;一JSON數組可以用於編碼Go言的數組和slice。一JSON象是一字符串到值的映射,成以列的name:value形式,用花括包含以逗分隔JSON的對象類型可以用於編碼Go言的mapkey型是字符串)和結構體。例如:
些基础类型可以通JSON的数组和对象类型进行递归组合。一JSON数组是一有序的值序列,在一方括号中并以逗分隔;一JSON数组可以用于编码Go言的数组和slice。一JSON象是一字符串到值的映射,成以列的name:value形式,用花括包含以逗分隔JSON的对象类型可以用于编码Go言的mapkey型是字符串)和结构体。例如:
```
boolean true
@@ -20,7 +20,7 @@ object {"year": 1980,
"medals": ["gold", "silver", "bronze"]}
```
慮一個應用程序,程序負責收集各種電影評論併提供反功能。它的Movie數據類型和一典型的表示影的值列表如下所示。(在結構體聲明中Year和Color成員後面的字符串面值是結構體成員Tag我們稍後會解釋它的作用。)
虑一个应用程序,程序负责收集各种电影评论并提供反功能。它的Movie数据类型和一典型的表示影的值列表如下所示。(在结构体声明中Year和Color成员后面的字符串面值是结构体成员Tag我们稍后会解释它的作用。)
<u><i>gopl.io/ch4/movie</i></u>
```Go
@@ -42,7 +42,7 @@ var movies = []Movie{
}
```
這樣的數據結構特别合JSON格式且在兩種之間相互轉換也很容易。將一個Go言中似movies的結構體slice轉爲JSON的程叫編組marshaling編組通過調用json.Marshal函完成:
这样的数据结构特别合JSON格式且在两种之间相互转换也很容易。将一个Go言中似movies的结构体slice转为JSON的程叫编组marshaling编组通过调用json.Marshal函完成:
```Go
data, err := json.Marshal(movies)
@@ -52,7 +52,7 @@ if err != nil {
fmt.Printf("%s\n", data)
```
Marshal函數返還一個編碼後的字slice包含很的字符串,併且沒有空白縮進;我們將它摺行以便於顯示:
Marshal函数返还一个编码后的字slice包含很的字符串,并且没有空白缩进;我们将它折行以便于显示:
```
[{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingr
@@ -61,7 +61,7 @@ tors":["Paul Newman"]},{"Title":"Bullitt","released":1968,"color":true,"
Actors":["Steve McQueen","Jacqueline Bisset"]}]
```
這種緊湊的表示形式然包含了全部的信息,但是很難閲讀。爲了生成便於閲讀的格式,另一json.MarshalIndent函數將産生整齊縮進的輸出。該函數有兩個額外的字符串參數用於表示每一行出的前和每一個層級的縮進
这种紧凑的表示形式然包含了全部的信息,但是很难阅读。为了生成便于阅读的格式,另一json.MarshalIndent函数将产生整齐缩进的输出。该函数有两个额外的字符串参数用于表示每一行出的前和每一个层级的缩进
```Go
data, err := json.MarshalIndent(movies, "", " ")
@@ -71,7 +71,7 @@ if err != nil {
fmt.Printf("%s\n", data)
```
上面的代碼將産生這樣的輸出(譯註:在最後一個成員或元素後面併沒有逗分隔符):
上面的代码将产生这样的输出(译注:在最后一个成员或元素后面并没有逗分隔符):
```Json
[
@@ -103,18 +103,18 @@ fmt.Printf("%s\n", data)
]
```
編碼時,默使用Go語言結構體的成名字作JSON的象(通reflect反射技,我們將在12.6節討論)。隻有導出的結構體成員才會被編碼,這也就是我們爲什麽選擇用大字母開頭的成員名稱
编码时,默使用Go语言结构体的成名字作JSON的象(通reflect反射技,我们将在12.6节讨论)。只有导出的结构体成员才会被编码,这也就是我们为什么选择用大字母开头的成员名称
心的者可能已經註意到其中Year名字的成員在編碼後變成了released有Color成員編碼後變成了小字母開頭的color。是因爲構體成員Tag所致的。一個構體成員Tag是和在編譯階段關聯到該成員的元信息字符串:
心的者可能已经注意到其中Year名字的成员在编码后变成了released有Color成员编码后变成了小字母开头的color。是因为构体成员Tag所致的。一个构体成员Tag是和在编译阶段关联到该成员的元信息字符串:
```
Year int `json:"released"`
Color bool `json:"color,omitempty"`
```
結構體的成Tag可以是任意的字符串面值但是通常是一列用空格分隔的key:"value"鍵值對序列;因值中含義雙引號字符,因此成Tag一般用原生字符串面值的形式書寫。json開頭鍵名對應的值用於控製encoding/json包的編碼和解的行爲,併且encoding/...下面其它的包也遵循這個約定。成Tag中json對應值的第一部分用指定JSON象的名字,比如Go言中的TotalCount成員對應到JSON中的total_count象。Color成的Tag還帶了一個額外的omitempty選項,表示Go語言結構體成員爲空或零值不生成JSON象(里false零值。果然Casablanca是一黑白影,併沒有輸出Color成
结构体的成Tag可以是任意的字符串面值但是通常是一列用空格分隔的key:"value"键值对序列;因值中含义双引号字符,因此成Tag一般用原生字符串面值的形式书写。json开头键名对应的值用于控制encoding/json包的编码和解的行为,并且encoding/...下面其它的包也遵循这个约定。成Tag中json对应值的第一部分用指定JSON象的名字,比如Go言中的TotalCount成员对应到JSON中的total_count象。Color成的Tag还带了一个额外的omitempty选项,表示Go语言结构体成员为空或零值不生成JSON象(里false零值。果然Casablanca是一黑白影,并没有输出Color成
編碼的逆操作是解對應將JSON數據解碼爲Go言的數據結構Go言中一般叫unmarshalingjson.Unmarshal函完成。下面的代碼將JSON格式的電影數據解碼爲一個結構體slice結構體中隻有Title成。通過定義合適的Go語言數據結構,我可以選擇性地解JSON中感趣的成員。當Unmarshal函數調用返slice將被隻含有Title信息值填充其它JSON成員將被忽略。
编码的逆操作是解对应将JSON数据解码为Go言的数据结构Go言中一般叫unmarshalingjson.Unmarshal函完成。下面的代码将JSON格式的电影数据解码为一个结构体slice结构体中只有Title成。通过定义合适的Go语言数据结构,我可以选择性地解JSON中感趣的成员。当Unmarshal函数调用返slice将被只含有Title信息值填充其它JSON成员将被忽略。
```Go
var titles []struct{ Title string }
@@ -124,7 +124,7 @@ if err := json.Unmarshal(data, &titles); err != nil {
fmt.Println(titles) // "[{Casablanca} {Cool Hand Luke} {Bullitt}]"
```
多web服都提供JSON接口HTTP接口送JSON格式請求併返迴JSON格式的信息。爲了説明這一點,我們通過Github的issue査詢服務來演示似的用法。首先,我要定義合適的類型和常量:
多web服都提供JSON接口HTTP接口送JSON格式请求并返回JSON格式的信息。为了说明这一点,我们通过Github的issue查询服务来演示似的用法。首先,我要定义合适的类型和常量:
<u><i>gopl.io/ch4/github</i></u>
```Go
@@ -157,9 +157,9 @@ type User struct {
}
```
和前面一樣,卽使對應的JSON象名是小字母,每個結構體的成名也是聲明爲大小字母開頭的。因有些JSON成名字和Go結構體成員名字不相同因此需要Go語言結構體成員Tag指定對應的JSON名字。同,在解碼的時候也需要做同樣的處GitHub服務返迴的信息比我們定義的要多很多。
和前面一样,即使对应的JSON象名是小字母,每个结构体的成名也是声明为大小字母开头的。因有些JSON成名字和Go结构体成员名字不相同因此需要Go语言结构体成员Tag指定对应的JSON名字。同,在解码的时候也需要做同样的处GitHub服务返回的信息比我们定义的要多很多。
SearchIssues函數發出一HTTP求,然後解碼返迴的JSON格式的果。因爲用戶提供的査詢條件可能包含`?``&`的特殊字符,了避免URL造成突,我用url.QueryEscape來對査詢中的特殊字符進行轉義操作。
SearchIssues函数发出一HTTP求,然后解码返回的JSON格式的果。因为用户提供的查询条件可能包含`?``&`的特殊字符,了避免URL造成突,我用url.QueryEscape来对查询中的特殊字符进行转义操作。
<u><i>gopl.io/ch4/github</i></u>
```Go
@@ -198,9 +198,9 @@ func SearchIssues(terms []string) (*IssuesSearchResult, error) {
}
```
在早些的例子中,我使用了json.Unmarshal函數來將JSON格式的字符串解碼爲字節slice。但是這個例子中,我使用了基流式的解器json.Decoder它可以從一個輸入流解JSON數據,盡管這不是必的。如您所料,有一個針對輸出流的json.Encoder編碼對象。
在早些的例子中,我使用了json.Unmarshal函数来将JSON格式的字符串解码为字节slice。但是这个例子中,我使用了基流式的解器json.Decoder它可以从一个输入流解JSON数据,尽管这不是必的。如您所料,有一个针对输出流的json.Encoder编码对象。
們調用Decode方法填充量。里有多方法可以格式化結構。下面是最簡單的一,以一固定度打印每issue但是在下一節我們將看到如果利用模闆來輸出複雜的格式。
们调用Decode方法填充量。里有多方法可以格式化结构。下面是最简单的一,以一固定度打印每issue但是在下一节我们将看到如果利用模板来输出复杂的格式。
<u><i>gopl.io/ch4/issues</i></u>
```Go
@@ -228,7 +228,7 @@ func main() {
}
```
命令行參數指定檢索條件。下面的命令是査詢Go語言項目中和JSON解碼相關的問題,還有査詢返迴的結果:
命令行参数指定检索条件。下面的命令是查询Go语言项目中和JSON解码相关的问题,还有查询返回的结果:
```
$ go build gopl.io/ch4/issues
@@ -249,12 +249,12 @@ $ ./issues repo:golang/go is:open json decoder
#4237 gjemiller encoding/base64: URLEncoding padding is optional
```
GitHub的Web服接口 https://developer.github.com/v3/ 包含了更多的特性。
GitHub的Web服接口 https://developer.github.com/v3/ 包含了更多的特性。
**練習 4.10** 改issues程序據問題的時間進行分,比如不到一月的、不到一年的、超一年。
**练习 4.10** 改issues程序据问题的时间进行分,比如不到一月的、不到一年的、超一年。
**練習 4.11** 編寫一個工具,允許用戶在命令行建、取、更新和關閉GitHub上的issue必要的候自動打開用戶默認的編輯器用於輸入文本信息。
**练习 4.11** 编写一个工具,允许用户在命令行建、取、更新和关闭GitHub上的issue必要的候自动打开用户默认的编辑器用于输入文本信息。
**練習 4.12** 流行的web漫畵服務xkcd也提供了JSON接口。例如 https://xkcd.com/571/info.0.json 請求將返迴一個很多人喜的571編號的詳細描述。下載每個鏈接(隻下載一次)然後創建一個離線索引。編寫一個xkcd工具使用這些離線索引,打印和命令行入的檢索詞相匹配的漫的URL。
**练习 4.12** 流行的web漫画服务xkcd也提供了JSON接口。例如 https://xkcd.com/571/info.0.json 请求将返回一个很多人喜的571编号的详细描述。下载每个链接(只下载一次)然后创建一个离线索引。编写一个xkcd工具使用这些离线索引,打印和命令行入的检索词相匹配的漫的URL。
**練習 4.13** 使用開放電影數據庫的JSON服接口,允許你檢索和下 https://omdbapi.com/ 上影的名字和對應的海報圖像。編寫一個poster工具命令行入的影名字,下載對應的海
**练习 4.13** 使用开放电影数据库的JSON服接口,允许你检索和下 https://omdbapi.com/ 上影的名字和对应的海报图像。编写一个poster工具命令行入的影名字,下载对应的海