浅谈Golang中Json反序列化的一些 “坑” !

菜鸟程序猿学习Go语言时遇到的一些坑
???

1、反序列化结构体 的“字段/属性”要求要与 序列化时结构体 的“字段/属性”必须保持一致。

简单的来说就是序列化定义的结构体,在反序列化的时候,结构体 标识符 可以不一样(可以理解为结构体的名字),但是结构体的内部 字段/属性 要一致
举个例子:
结构体序列化之前

type Hero struct {
	Name string `json:"hero_name"` //反射,Go中通过 对命名的首字母大写来确认公有
	Age int
	Skill string
} 

func main() {
	hero := Hero {
			Name :"SuperMan ~",
			Age : 1 ,
			Skill : "镭射眼",
		}

		//将Hero 序列化
		data, err := json.Marshal(&hero) //序列化函数
		if err != nil {
			fmt.Printf("序列号错误 err=%v\n", err)
		}
		//输出序列化后的结果
		fmt.Printf("Hero序列化后=%v\n", string(data))
	}

结果为:

终端显示 : {"Name":"SuperMan ~","Age" : 1 ,"Skill" : "镭射眼"}

结构体反序列化:

type ParallelUniverseHero struct {
	Name string
	Age int
	Skill string
} 
str := "{\"Name\":\"SuperMan ~\",\"Age\":1,\"Skill\":\"镭射眼\"}" //系统读取的字符串可以不用加“\”转译,手动输入的需要转译

	//定义一个Monster实例
	var PUhero Monster

	err := json.Unmarshal([]byte(str), &PUhero) //反序列化函数
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化后 PUhero=%\n", PUhero)

结果为:

终端显示 : {"Name":"SuperMan ~","Age" : 1 ,"Skill" : "镭射眼"}
(比较懒就不截图了 =v= !)

从两段代码中可以看到结构体的标识符(名字),并不一样,但是仍然可以正常的获取输出。但是如果结构体的字段个数或内容不一致,就会出现异常结果,或为初始定义时的空内容或0或false。(这里不会报错!而且还可以执行通过,编辑器检查不出来,很坑!很有可能出现字段内容为空的问题。会正常显示内容,但是内容是错误的)

2、反序列化Map或Slice的类型要求要与 序列化时Map或Slice的类型必须保持一致。

对于Map和Slice的反序列化,对类型上有严格的要求。下面我拿map举例,Slice是类似的。
代码:

序列化Map

func testmap() string {
	//定义一个map
	var batman map[string]interface{}  //使用map时,需要先 make 在内存中开辟空间
	batman = make(map[string]interface{})
	batman["name"] = "BatMan"
	batman["age"] = 30
	batman["skill"] = "有钱!"

	//将 batman 这个map进行序列化
	data, err := json.Marshal(batman)
	if err != nil {
		fmt.Printf("序列化错误 err=%v\n", err)
	}
	//输出序列化后的结果
	//fmt.Printf("batman 序列化后=%v\n", string(data))
}

得到的结果是:

控制台输出:batman 序列化后=map[skill:有钱! age:30 name:BatMan

反序列化Map:

	str := testmap() //这里直接使用map的序列化中的Json字符串
	
	//定义一个map
	var a map[string]interface{}

	//反序列化
	//注意:反序列化map,不需要make,因为make操作被封装到 Unmarshal函数
	err := json.Unmarshal([]byte(str), &a)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化 batman的类型:%T", a)
	fmt.Printf("反序列化后 batman=%v\n", a)

结果是:

控制台输出 batman 反序列化后=map[skill:有钱! age:30 name:BatMan]

如果map的类型不一样的话

	str := "{\"skill\":\"有钱!\",\"age\":30,\"name\":\"BatMan\"}"
	
	//定义一个map,这里类型为[byte],而不是之前的[string]
	var a map[byte]interface{}

	err := json.Unmarshal([]byte(str), &a)
	if err != nil {
		fmt.Printf("unmarshal err=%v\n", err)
	}
	fmt.Printf("反序列化 batman的类型:%T", a)
	fmt.Printf("反序列化后 batman=%v\n", a)

结果就会出现:

unmarshal err=json: cannot unmarshal number skill into Go value of type uint8
反序列化 batman的类型:map[uint8]interface {}
反序列化后 batman=map[]

Slice报出的提示语和Map相同提示如下:
unmarshal err=json: cannot unmarshal number age into Go value of type uint8
反序列化后 slice=[map[] map[] map[] map[] map[]]

但仍然不会报错!!!可以执行通过!!!不过相比于结构体起码有个提示语。

未完待续…以后会陆续更新~~~

你可能感兴趣的:(浅谈Golang中Json反序列化的一些 “坑” !)