1. 简介
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。其语法上类似于 JavaScript 的对象和列表。最常用于 web 后端之间的通信和在浏览器中运行 JavaScript 程序,但是其它地方也大量使用。其主页:json.org,提供了一个非常清晰和简明定义的标准。
使用 json 包 可以很容易的在 GO 程序中读写 JSON 数据。
2. 编码
使用 Marshal 函数生成 JSON 数据。
func Marshal(v interface{}) ([]byte, error)
给定 GO 数据的结构体:Message
,
type Message struct {
Name string
Body string
Time int64
}
然后获取 Message
的一个实例。
m := Message{"Alice", "Hello", 1294706395881547000}
使用 json.Marshal
获得一个 JSON 格式的 m。
b, err := json.Marshal(m)
如果一切顺利,err
将会为 nil
,b
将会是一个包含 JSON 数据的 []byte
b == []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)
只有当数据结构体能被表示成合法的 JSON 时,才会被编码。
- JSON 对象只支持 strings 类型作为键名;必须使用 map[string]T来编码成 Go map 类型(其中
T
是任意一种 json 包支持的 Go 类型)。 - Channel,complex 和函数类型不能被编码。
- 不支持循环的数据结构,将会导致
Marshal
进入死循环。 - 指针将被编码成它们指向的值(或’null’,如果指针是零)。
json包只访问公开字段的结构体类型(以大写字母开头的那些),因此只有公开字段的结构体会出现在 JSON 输出中。
示例代码 :
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
type ColorGroup struct {
ID int
Name string
Colors []string
}
group := ColorGroup{
ID: 1,
Name: "Reds",
Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(b)
}
3. 解码
使用 Unmarshal 函数解析 JSON 数据。
func Unmarshal(data []byte, v interface{}) error
首先必须创建一个存放解析数据的地方。
var m Message
然后调用 json.Unmarshal
,传入一个包含 JSON 数据的 []byte
和一个指针 m。
err := json.Unmarshal(b, &m)
如果 b
包含适合 m
的有效的 JSON 数据,那么调用 err
将会是nil
,然后数据将会从 b
保存到结构体 m
中,就像赋值:
m = Message{
Name: "Alice",
Body: "Hello",
Time: 1294706395881547000,
}
使用 Unmarshal
时,如何定义用于保存解码数据的字段?对于给定的键 "Foo"
,Unmarshal
将会浏览目标结构体来查找相应字段。(按优先顺序排列)
- 一个标签为
"Foo"
的公开字段(更多结构体标签查看 Go spec), - 一个名称为
"Foo"
的公开字段,或 - 一个名称为
"FOO"
或"FoO"
或一些其它的不区分大小写匹配"Foo"
的公开字段。
如果 JSON 数据的结构体与 Go 类型不完全匹配?
b := []byte(`{"Name":"Bob","Food":"Pickle"}`)
var m Message
err := json.Unmarshal(b, &m)
Unmarshal
只解析目标类型中定义的字段。在这个例子中,只有 m 的 Name 字段会被解析,而 Food 字段将被忽略。当只希望从大的 JSON 数据中选择少量特定字段时,该行为非常实用。这也意味着任何目标结构体的私有字段将不受 Unmarshal
影响。
示例代码 :
package main
import (
"encoding/json"
"fmt"
)
func main() {
var jsonBlob = []byte(`[
{"Name": "Platypus", "Order": "Monotremata"},
{"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
Name string
Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)
}
4. 笔记
- 自定义输出的 JSON 数据的键名,在字段类型后使用反单引号
json:" "
:
type Animal struct {
Name string `json:"name"`
Order string
}
- 如果双引号中间是
-
,该字段将不会输出:
type Animal struct {
Name string `json:"-"`
Order string
}
参考资料
Go 博客:http://blog.golang.org/json-and-go
Go 编程语言 json 包:https://golang.org/pkg/encoding/json/
rgyq 博客:http://rgyq.blog.163.com/blog/static/316125382013934153244/
有疑问加站长微信联系(非本文作者)