需要程序都需要处理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接口就可以了

发表评论

邮箱地址不会被公开。 必填项已用*标注