开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
import "encoding/json"
encoding
编码成JSON数据
func Marshal(v interface{}) ([]byte, error)
type Message struct {
Name string
Body string
Time int64
}
m := Message{"Alice", "Hello", 1294706395881547000}
b, err := json.Marshal(m)
只有可以表示为json的数据结构能编码成json map数据类型也可以编码为json
var m = map[string]interface{}{
"name": "Alice",
"age": 15,
}
b, err := json.Marshal(m)
decoding
解码JSON数据
func Unmarshal(data []byte, v interface{}) error
将json数据data解码存储到v中;
var n Message
// 将解码后的数据存储到n中
err =json.Unmarshal(b, &n)
- Unmarshal方法是如何识别解码后的数据应该对应哪个字段的呢?
比如对于json的keyname
,Unmarshal会在指定的结构(Message)中查找匹配的字段(字段必须以大写字母开头,因为只有导出的字段才能被编码/解码为JSON);
- 当JSON的数据结构与Go数据类型不完全匹配怎么办?
Unmarshal只会解码能匹配到的字段,没有匹配到的就空着;
- 如果事先不知道JSON数据的结构怎么办?应该用什么数据结构来接收?
空接口:interface{}
关于接口与空接口:
接口类型是由一组方法签名组成的集合,实现接口的方式就是实现这个接口的所有方法
空接口:指定了零个方法的接口;
每个Go类型都至少实现了零个方法,所以相当于实现了空接口; 可以用类型断言获取底层数据;
类型断言提供了访问接口值底层具体值的方式;
t := i.(T)
该语句断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t。
若 i 并未保存 T 类型的值,该语句就会触发一个panic。
为了判断一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。
t, ok := i.(T)
若 i 保存了一个 T类型的值,那么 t 将会是其底层值,而 ok 为 true。
否则,ok 将为 false 而 t 将为 T 类型的零值,程序并不会产生恐慌。
如果不知道底层类型,则可以用switch来确定
var f interface{}
err = json.Unmarshal(y, &f)
if err == nil {
m := f.(map[string]interface{})
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, " is string ", vv)
case float64:
fmt.Println(k, " is float64 ", vv)
case int:
fmt.Println(k, " is int ", vv)
case bool:
fmt.Println(k, " is bool ", vv)
case []interface{}:
fmt.Println(k, " is array ")
for i, a := range vv {
fmt.Println(i, " : ", a)
}
default:
fmt.Println(k, " don't know ", vv)
}
}
}
这种方式的好处是使用未知的JSON数据的同时仍然做到类型安全;
json 包使用 map[string]interface{}
和 []interface{}
来存储 JSON 对象和数组;它会愉快地将任何有效的 JSON blob 解组为普通 interface{}
值。默认的具体 Go 类型是:
bool对应 JSON 布尔值,
float64、整数对应 JSON 数值,
数组和切片值编码为 JSON 数组,
string对于 JSON 字符串,
nil对于 JSON 为空。
也可以直接解码成map[string]interface{}
var y = []byte(`{"name":"Bob","age":20,"score":96.4,"first":false,"hobby":["eat","game"]}`)
var c = make(map[string]interface{})
err := json.Unmarshal(y, &c)
if err == nil {
fmt.Println(c)
}
流编码器和流解码器
json 包提供Decoder和Encoder类型来支持读取和写入 JSON 数据流的常见操作;
func NewDecoder(r io.Reader) *Decoder
func NewEncoder(w io.Writer) *Encoder
从标准输入中读取JSON对象;
由于 Reader 和 Writers 无处不在,这些Encoder
和Decoder
类型可用于广泛的场景,例如读取和写入 HTTP 连接、WebSocket 或文件