12.9 Json 数据格式

最后更新于:2022-04-01 20:57:18

## 12.9 Json 数据格式 数据结构要在网络中传输或保存到文件,就必须对其编码和解码;目前存在很多编码格式:JSON,XML,gob,Google 缓冲协议等等。Go 语言支持所有这些编码格式;在后面的章节,我们将讨论前三种格式。 结构可能包含二进制数据,如果将其作为文本打印,那么可读性是很差的。另外结构内部可能包含匿名字段,而不清楚数据的用意。 通过把数据转换成纯文本,使用命名的字段来标注,让其具有可读性。这样的数据格式可以通过网络传输,而且是与平台无关的,任何类型的应用都能够读取和输出,不与操作系统和编程语言的类型相关。 下面是一些术语说明: * 数据结构 --> 指定格式 = `序列化` 或 `编码`(传输之前) * 指定格式 --> 数据格式 = `反序列化` 或 `解码`(传输之后) 序列化是在内存中把数据转换成指定格式(data -> string),反之亦然(string -> data structure) 编码也是一样的,只是输出一个数据流(实现了 io.Writer 接口);解码是从一个数据流(实现了 io.Reader)输出到一个数据结构。 我们都比较熟悉 XML 格式(参阅 [12.10](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/12.9.md));但有些时候 JSON(JavaScript Object Notation,参阅 [http://json.org](http://json.org/))被作为首选,主要是由于其格式上非常简洁。通常 JSON 被用于 web 后端和浏览器之间的通讯,但是在其它场景也同样的有用。 这是一个简短的 JSON 片段: ~~~ { "Person": { "FirstName": "Laura", "LastName": "Lynn" } } ~~~ 尽管 XML 被广泛的应用,但是 JSON 更加简洁、轻量(占用更少的内存、磁盘及网络带宽)和更好的可读性,这也说明它越来越受欢迎。 Go 语言的 json 包可以让你在程序中方便的读取和写入 JSON 数据。 我们将在下面的例子里使用 json 包,并使用练习 10.1 vcard.go 中一个简化版本的 Address 和 VCard 结构(为了简单起见,我们忽略了很多错误处理,不过在实际应用中你必须要合理的处理这些错误,参阅 13 章) 示例 12.16 [json.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_12/json.go): ~~~ // json.go.go package main import ( "encoding/json" "fmt" "log" "os" ) type Address struct { Type string City string Country string } type VCard struct { FirstName string LastName string Addresses []*Address Remark string } func main() { pa := &Address{"private", "Aartselaar", "Belgium"} wa := &Address{"work", "Boom", "Belgium"} vc := VCard{"Jan", "Kersschot", []*Address{pa, wa}, "none"} // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: // JSON format: js, _ := json.Marshal(vc) fmt.Printf("JSON format: %s", js) // using an encoder: file, _ := os.OpenFile("vcard.json", os.O_CREATE|os.O_WRONLY, 0) defer file.Close() enc := json.NewEncoder(file) err := enc.Encode(vc) if err != nil { log.Println("Error in encoding json") } } ~~~ `json.Marshal()` 的函数签名是 `func Marshal(v interface{}) ([]byte, error)`,下面是数据编码后的 JSON 文本(实际上是一个 []bytes): ~~~ { "FirstName": "Jan", "LastName": "Kersschot", "Addresses": [{ "Type": "private", "City": "Aartselaar", "Country": "Belgium" }, { "Type": "work", "City": "Boom", "Country": "Belgium" }], "Remark": "none" } ~~~ 出于安全考虑,在 web 应用中最好使用 `json.MarshalforHTML()` 函数,其对数据执行HTML转码,所以文本可以被安全地嵌在 HTML ` ';