一、前言
其实本篇应该写的是json的反序列化,所以花了几个晚上看了下该部分源码,每次看都想睡觉。为什么呢?因为确实是太无聊了,我打赌这是我看过go源码中最无聊的逻辑,全篇都是一些状态的切换,要么是 if ... else ...
,要么就是switch ... case ... case ...
,头大。我也尝试画过流程图,但是这么多状态的切换,也不知道是什么力量支撑我画了2天时间,最后我放弃了-画出来没有丝毫意义。所以本篇我就源码层面顺着json:你或许还不知道的使用的坑(一)续写下反序列化可能会遇到的一些坑或者未知的使用方法。
tips:
- 我在看的过程中也留了些注释,看兴趣的话可以去GitHub上去看看,也欢迎你的加入。
- 所有代码在
The Go Playground
都能看到。
二、内容
1.反序列化科学计数法
假如你有这么个json字符串,如何序列化呢?
{
"Name": "zhangSan",
"Age": -0e+10000
}
注意Age
字段的值并没有被双引号包围,所以go提供了一种类型json.Number
专门用来装数字,包括科学计数法和普通数字。下面是我的结构体:
type User struct {
Name string
Age json.Number
}
运行我的示例代码能得到正确结果:
{
zhangSan -0e+10000}
2.value是null的注意
假如我有这么个json字符串:
{
"Name": null,
"Age": null
}
且我的结构体是这样的:
type User struct {
Name string
Age map[string]string
}
我的序列化代码如下:
var san = User{
Name: "aaa",
Age: map[string]string{
"1": "1"},
}
err := json.Unmarshal(bytes, &san)
if err != nil {
fmt.Println("error:", err)
} else {
fmt.Println(san)
}
你觉得打印结果会是神马样子的呢?
{
aaa map[]}
会有点不可思议是吧?为什么Name
的值没有改变,但是Age
确被重新初始化了呢?
go的官方序列化代码如下:
case 'n': // null
// The main parser checks that only true and false can reach here,
// but if this was a quoted string input, it could be anything.
if fromQuoted && string(item) != "null" {
// 字段有',string'标签,以n开头,必须是null
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
break
}
switch v.Kind() {
case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: // 设置给interface{},指针,map,切片一个初始化的值
v.Set(reflect.Zero(v.Type()))