JSON
(JavaScript Object Notations)是一种简单的数据交互格式,经常用于不同系统之间的信息交换。
Go
语言中的encoding/json
根据RFC 7159规范实现了JSON
的编码解码。
编码
将Go
语言中的结构编码为Json
1 | func Marshal(v interface{}) ([]byte, error) |
1 | package main |
只有能被表达为有效的JSON
格式的Go
数据类型才能被正确的编码:
JSON
对象只支持字符串作为键;被编码的结构体必须符合如下格式map[string]T
(T为json package支持的任意Go
类型)
-Channel
,Complex
,func
不能被编码
- 不支持循环的数据结构;会导致Marshal
掉入无限循环
- 如果数据类型是指针将会编码会指针指向的值(如果指针为nil
刚编码为null
)json package
只会处理结构体中以大写字母开头的字段
解码
将JSON
解码为Go
语言中的结构体
1
func Unmarshal(data []byte, v interface{}) error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package main
import (
"encoding/json"
"fmt"
)
type Message struct {
Name string
Body string
Time int64
}
func main() {
var m Message
b := []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`)
json.Unmarshal(b, &m)
fmt.Println(m)
fmt.Println(m.Body)
}
那Unmarshal
是如何解码JSON
中的数据,对于JSON
的字段是如何对应结构体的字段?
假如JSON
中有一个键为Foo
Unmarshal
首先会寻找导出字段
中有标签json:”Foo”的字段;如果不存在标签则会寻找导出字段``Foo
;如果还未找到,则会寻找导出字段
FOO,FoO或者其它忽略大小写的匹配。如果未找到匹配字段则会忽略。
解码任意结构的JSON
1 | package main |
Streaming Encoders and Decoders
json
包也提供了Decoder
和Encoder
类型来处理流式的JSON
数据。1
2func NewDecoder(r io.Reader) *Decoder
func NewEncoder(w io.Writer) *Encoder1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package main
import (
"encoding/json"
"log"
"os"
)
func main() {
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for {
var v map[string]interface{}
if err := dec.Decode(&v); err != nil {
log.Println(err)
return
}
for k := range v {
if k != "Name" {
delete(v, k)
}
}
if err := enc.Encode(&v); err != nil {
log.Println(err)
}
}
}
上面代码实现的功能是从标准输入读取数据,先进行解码,然后判断键如果不等于Name则删除,最后输出到标准输出。
struct field tags
1 | // 编码为json时,字段Name名称会被改写为myName |
结构体嵌套1
2
3
4
5
6
7
8
9
10type Embedded struct {
F1 int
F2 string
}
// 在结构体中嵌套结构体Extra,需指定为inline
type Foo struct {
Name `json:"name"`
Embedded `json:",inline"`
}
Ref:
1.https://blog.golang.org/json
2.https://golang.org/pkg/encoding/json/
3.https://play.golang.org/p/NnwTh9KI5r