需要程序都需要处理XML和JSON
对于这类的处理,标准库提供了JSON和XML的包
现在,JSON远比XML流行,毕竟XML携带的标签多,JSON处理的标签更少,JSON可以转换为更小的BSON,但是无论哪种,我们在Go的标准库中都能看见
首先是 JSON的解码
json包的NewDecoder函数和Decoder方法进行
如果需要处理网络响应的JSON
会用到这个函数或者方法,我们看一下GET请求响应的JSON的例子
// GET请求获取响应,并将其转换为结构
package main
import (
“encoding/json”
“fmt”
“log”
“net/http”
)
type (
// 声明一个结构
gResult struct {
GsearchResultClass string `json:”GsearchResultClass”`
UnescapedURL string `json:”unescapedUrl”`
URL string `json:”url”`
VisibleURL string `json:”visibleUrl”`
CacheURL string `json:”cacheUrl”`
Title string `json:”title”`
TitleNoFormatting string `json:”titleNoFormatting”`
Content string `json:”content”`
}
// 进行上层的组合结构
gResponse struct {
ResponseData struct {
Results []gResult `json:”results”`
} `json:”responseData”`
}
)
func main() {
uri := “http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=8&q=golang”
// 获取相应
resp, err := http.Get(uri)
if err != nil {
log.Println(“ERROR:”, err)
return
}
defer resp.Body.Close()
// 转换为gResponse
var gr gResponse
err = json.NewDecoder(resp.Body).Decode(&gr)
if err != nil {
log.Println(“ERROR:”, err)
return
}
fmt.Println(gr)
上面我们声明结构的时候,使用单引号声明了一个字符串,这些字符串被称为标签 tag
是一种提供给解码器的方式,将JSON文档中的key和结构中的字段一一对应
如果不存在标签,编码和解码的过程会试图以一种大小写无关的方式,直接按照字段名字匹配
如果匹配不上,对应的结构字段为nil
然后就是NewDecoder和Decode方法的声明
NewDecoder的函数接收一个实现了io.Reader类型的值作为参数
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
然后在Decoder中中,我们接受一个实现了空接口 interface{}的结构,任何的结构都默认都实现了interface{},所以可以直接使用Decoder
Deocder中会利用反射进行解析
然后,在代码中,我们声明了gResponse的指针,然后传入这个变量指针
然后返回一个error,如果error不为空,说明Decoder对其进行了初始化
这是一种反序列化的方式
还有就是JSON文档以string存在,如何反序列化
代码如下,基本上使用了json的Unmarshal函数
package main
import (
“encoding/json”
“fmt”
“log”
)
// Contact represents our JSON string.
type Contact struct {
Name string `json:”name”`
Title string `json:”title”`
Contact struct {
Home string `json:”home”`
Cell string `json:”cell”`
} `json:”contact”`
}
// JSON contains a sample string to unmarshal.
var JSON = `{
“name”: “Gopher”,
“title”: “programmer”,
“contact”: {
“home”: “415.333.3333”,
“cell”: “415.555.5555”
}
}`
func main() {
// Unmarshal the JSON string into our variable.
var c Contact
err := json.Unmarshal([]byte(JSON), &c)
if err != nil {
log.Println(“ERROR:”, err)
return
}
fmt.Println(c)
}
如果无法为一个JSON来声明一个格式
可以尝试解码到一个map变量中,如下所示
// This sample program demonstrates how to decode a JSON string.
package main
import (
“encoding/json”
“fmt”
“log”
)
// JSON contains a sample string to unmarshal.
var JSON = `{
“name”: “Gopher”,
“title”: “programmer”,
“contact”: {
“home”: “415.333.3333”,
“cell”: “415.555.5555”
}
}`
func main() {
// Unmarshal the JSON string into our map variable.
var c map[string]interface{}
err := json.Unmarshal([]byte(JSON), &c)
if err != nil {
log.Println(“ERROR:”, err)
return
}
fmt.Println(“Name:”, c[“name”])
fmt.Println(“Title:”, c[“title”])
fmt.Println(“Contact”)
fmt.Println(“H:”, c[“contact”].(map[string]interface{})[“home”])
fmt.Println(“C:”, c[“contact”].(map[string]interface{})[“cell”])
}
将其中的结构类型变量替换为map的变量
声明为一个map类型,key为strnig,值为interface{}
map中可以声明为任何类型的值,但是上面有一个缺点,就是我们处理contact字段
因为contact字段也是一个映射,所以并不好处理
然后就是序列化
利用json中MarshalIndent函数,就可以将map或者结构类型的值,转换为易读的JSON文档
例子如下
// This sample program demonstrates how to marshal a JSON string.
package main
import (
“encoding/json”
“fmt”
“log”
)
func main() {
// Create a map of key/value pairs.
c := make(map[string]interface{})
c[“name”] = “Gopher”
c[“title”] = “programmer”
c[“contact”] = map[string]interface{}{
“home”: “415.333.3333”,
“cell”: “415.555.5555”,
}
// 进行序列化为JSON字符串
data, err := json.MarshalIndent(c, “”, ” “)
if err != nil {
log.Println(“ERROR:”, err)
return
}
fmt.Println(string(data))
}
我们看一下json包中的MarshalIndent函数如何将一个map值转换为JSON字符串,函数MarshalIndent返回一个byte切片,保存JSON字符串和error值
声明如下
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
我们利用interface这个空接口
如果不需要格式化,那么还有一个Marshal的函数来进行解码
在本章中,说明了Go提供了JSON和XML对应的解编码的基本功能
而且只要传入支持io.Reader和io.Writer接口就可以了