介绍:
json 是一种常见的数据交互模式, 从语法来看, 他类似于javascript 的 对象和列表。 通常情况下, json 被用于在web 后端服务器和 运行在浏览器上的js 程序进行通信, 偶尔, 该数据结构也用被其他地方用于通信。
你可以使用json 包在你的go 程序中非常简单的读写json.
编码:
编码json 数据可以使用 Marshal 函数
func Marshal(v interface{}) ([]byte, error)
下面给出go 数据结构: Message
type Message struct {
Name string
Body string
Time int64
}
和 Message 的实例: m
m := Message{"Alice", "Hello", 1294706395881547000}
我们能够使用 json.Marshal 方法得到一个m实例的json 字符串([]byte)
b, err := json.Marshal(m);
如果我们的语法正确, 则 err 变量的值为 nil, 且b 变量([]byte)中会保存json 数据
b == []byte(`{"Name":"Alice","Body":"Hello","Time":1294706395881547000}`) ps: go 中使用反引号或两个双引号来表示一个字符串, 两种方法略有分别, 可以搜索 'go 反引号 双引号 的相关博客'
以下是一些合法json 编码的规则
json 对象只支持使用字符串为key; 在编码 map 类型时, map 的形式应该为 map[string]T (T 是json 包中支持的变量类型)
管道类型、 复杂类型、 函数类型不能被编码为json
不支持循环结构, 这样会导致Marshal 函数死循环
json 包仅仅会访问结构体类型的导出字段(结构体成员变量已大写字母开头), 所以, 输出的json 串只会包含结构体的导出字段。
解码:
我们可以使用Unmarshal 函数解码json 数据
func Unmarshal(data []byte, v interface{}) error
我们必须提前创建好保存json 对象的数据结构
var m Message
然后, 调用 json.Unmarshal, 传入含有json 数据的b ([]byte) 和 m (Message)的指针
err := json.Unmarshal(b, &m);
如果 b 中的json 串合法, 则err 变量的值为 nil ; 同时, 会把b 中的数据存储在 m 中 , 这个过程类似于下面的赋值操作:
m = Message{
Name: "Alice",
Body: "Hello",
Time: 1294706395881547000,
}
现在, 我们来思考一个问题, Unmarshal 是如何将对应的值存入结构体相应的字段中呢? 举个栗子, Json 中有一个 key -- "Foo", Unmarshal 函数是如何找到结构体中对应的 Foo 成员并赋值的呢?
Unmarshal 函数反序列化的规则如下:
找到一个导出字段的 tag 叫 "Foo" 的
找到一个 导出字段叫 "Foo" 的
按照忽略大小写匹配导出字段为 "Foo" 的 (例如 : FOO FoO FOo 都算)
因为涉及到匹配,那么, 如果json 串中的key 没有匹配 go 语言中的类型会怎么样呢? 比如说:
b := []byte(`{"Name":''Bob", "Food":"Pickle"}`)
var m Message
err := json.Unmarshal(b, &m);
在上面的例子中, Unmarshal 函数会尽量将匹配的字段赋值。 也就是说 只有 Name 字段会被复制, Food 字段将会忽略掉。
以上是已知json 数据内容的情况, 这样可以自定义结构体, 如果json 结构体未知呢? 预知后事如何, 请听下回分解
有疑问加站长微信联系(非本文作者))