Go如何實(shí)現(xiàn)json字符串與各類(lèi)struct相互轉(zhuǎn)換
json字符串與各類(lèi)struct相互轉(zhuǎn)換
不廢話(huà)了都在代碼中了
package main import ( "fmt" "reflect" "encoding/json" "strings" ) type Class struct { Grade int `json:"grade"` //年級(jí) ClassNumber int `json:"classNumber"` //班級(jí)號(hào) } type Student struct{ Name string //大寫(xiě)開(kāi)頭,可被導(dǎo)出,沒(méi)有`json:".."`,導(dǎo)出json的字段名是原本名稱(chēng) age int //小寫(xiě)開(kāi)題,不可被導(dǎo)出 Hight int `json:"currentHight"` //導(dǎo)出對(duì)應(yīng)json的字段名為currentHight Class *Class `class` //指針,指向引用對(duì)象;如果不用指針,只是值復(fù)制 } func doMarshal(){//對(duì)象轉(zhuǎn)json字符串 nClass:=new(Class)//new只給給特定類(lèi)型分配內(nèi)存,設(shè)置“零”值,返回其地址(指針) fmt.Printf("nClass的類(lèi)型是%s,內(nèi)容是%v\n",reflect.TypeOf(nClass),*nClass) nClass.Grade=3 nClass.ClassNumber=6 nStudents:=make([]*Student,0) //make只用于map,slice和channel,并且不顯示返回指針 //這個(gè)切片,存放Student的指針 nStudent:=Student{"Lily",7,116,nClass} jsonBytes,err1:=json.Marshal(nStudent)//解析后的是[]byte if err1!=nil{ fmt.Printf("轉(zhuǎn)json失敗:%v\n",err1) return } fmt.Println("轉(zhuǎn)成的JSON:") //age不會(huì)被導(dǎo)出 //{"Name":"Lily","currentHight":116,"Class":{"grade":3,"classNumber":6}} fmt.Println(string(jsonBytes)) nStudents=append(nStudents,&Student{"Lilei",8,130,nClass}) nStudents=append(nStudents,&nStudent) josnListBytes,err2:=json.Marshal(nStudents) if err2!=nil{ fmt.Printf("轉(zhuǎn)jsonList失?。?v\n",err2) return } fmt.Println("轉(zhuǎn)成的列表型JSON:") fmt.Println(string(josnListBytes)) //[{"Name":"Lilei","currentHight":130,"Class":{"grade":3,"classNumber":6}},{"Name":"Lily","currentHight":116,"Class":{"grade":3,"classNumber":6}}] } func doUnMarshal(){//json字符串轉(zhuǎn)對(duì)象 jsonStr:=` { "Name":"Lily", "currentHight":116, "age":12, "Class":{ "grade":3, "classNumber":6 }, "score":[98,100,95] } ` jsonListStr:=`[ { "Name":"Lucy", "currentHight":120, "Class":{ "grade":3, "classNumber":5 } }, { "Name":"Lily", "currentHight":116, "Class":{ "grade":3, "classNumber":6 } } ]` //第一種解析json方式,解析到Struct/[]Struct student:=Student{}//同new(Student) err:=json.Unmarshal([]byte(jsonStr),&student) //Unmarshall第2個(gè)參數(shù)必須是指針,否則報(bào)錯(cuò):json: Unmarshal(non-pointer main.Student) //因?yàn)楸仨毥馕龅骄唧w的對(duì)象,所以需傳入對(duì)象引用,而不是值傳遞 //score在Student中沒(méi)有此字段,所以被忽略了 if err!=nil{ fmt.Printf("解析json字符串異常:%s\n",err) } fmt.Printf("學(xué)生的名稱(chēng)是%v,班級(jí)信息是%v,年齡是%v(私有對(duì)象不能導(dǎo)入,初始為0)\n",student.Name,*student.Class,student.age) //學(xué)生的名稱(chēng)是Lily,學(xué)生的班級(jí)信息是{3 6},學(xué)生的年齡是0 students:=[]*Student{} //定義切片,同make([]*Student,0) err=json.Unmarshal([]byte(jsonListStr),&students) if err!=nil{ fmt.Printf("解析json字符串異常:%s\n",err) } for _,stu:=range students{ //這里stu是指針類(lèi)型,獲取其屬性可以直接用.Name,也可以解引用后用.Name fmt.Printf("列表:學(xué)生的名稱(chēng)是%s,身高是%d,在%d年級(jí)%d班\n",stu.Name,(*stu).Hight,(*stu.Class).Grade,stu.Class.ClassNumber) } //第二種解析到interface{}/[]interface{} fmt.Println("*************解析json*************") var student1 interface{} err=json.Unmarshal([]byte(jsonStr),&student1) if err!=nil{ fmt.Printf("解析json字符串異常:%s\n",err) } c:=-1 resolve2JosnObj(student1,c) /* *************解析json************* map元素: map[Name]的元素: 類(lèi)型是string,值是 Lily map[currentHight]的元素: 類(lèi)型float64,值是 116 map[age]的元素: 類(lèi)型float64,值是 12 map[Class]的元素: map元素: ---map[classNumber]的元素: 類(lèi)型float64,值是 6 ---map[grade]的元素: 類(lèi)型float64,值是 3 map[score]的元素: list元素: ---第0個(gè)元素: 類(lèi)型float64,值是 98 ---第1個(gè)元素: 類(lèi)型float64,值是 100 ---第2個(gè)元素: 類(lèi)型float64,值是 95 */ fmt.Println("*************解析jsonlist*************") var students1 interface{} err=json.Unmarshal([]byte(jsonListStr),&students1) if err!=nil{ fmt.Printf("解析jsonlist字符串異常:%s\n",err) } d:=-1 resolve2JosnObj(students1,d) /* *************解析jsonlist************* list元素: 第0個(gè)元素: map元素: ---map[Name]的元素: 類(lèi)型是string,值是 Lucy ---map[currentHight]的元素: 類(lèi)型float64,值是 120 ---map[Class]的元素: map元素: ------map[grade]的元素: 類(lèi)型float64,值是 3 ------map[classNumber]的元素: 類(lèi)型float64,值是 5 第1個(gè)元素: map元素: ---map[Class]的元素: map元素: ------map[grade]的元素: 類(lèi)型float64,值是 3 ------map[classNumber]的元素: 類(lèi)型float64,值是 6 ---map[Name]的元素: 類(lèi)型是string,值是 Lily ---map[currentHight]的元素: 類(lèi)型float64,值是 116 */ } func resolve2JosnObj(objI interface{},c int){ c=c+1 switch obj:=objI.(type) { //此處[interface{}].(type) 專(zhuān)門(mén)用于switch的類(lèi)型判斷 case string: fmt.Println("類(lèi)型是string,值是",obj) case float64: fmt.Println("類(lèi)型float64,值是",obj) case map[string]interface{}: fmt.Println("map元素:") for k,vi:=range obj{ fmt.Printf("%smap[%s]的元素: ",strings.Repeat("---",c),k) resolve2JosnObj(vi,c) } case []interface{}: fmt.Println("list元素:") for i,vi:=range obj{ fmt.Printf("%s第%d個(gè)元素: ",strings.Repeat("---",c),i) resolve2JosnObj(vi,c) } default: fmt.Println("無(wú)法判斷類(lèi)型,類(lèi)型是",reflect.TypeOf(obj),"值是",obj) } } func main() { doMarshal()//對(duì)象轉(zhuǎn)json字符串 doUnMarshal() }
簡(jiǎn)單總結(jié)
1、結(jié)構(gòu)體對(duì)象可生成json字符串,Marshal()是[]byte,需要string去轉(zhuǎn)換
2、json字符串可以映射到一個(gè)struct,但僅限公共元素(大寫(xiě)開(kāi)頭);也可通用的轉(zhuǎn)換到空接口interfece[],使用對(duì)應(yīng)轉(zhuǎn)換到需要的內(nèi)容
結(jié)構(gòu)體轉(zhuǎn)換為JSON字符串的一個(gè)坑
通過(guò)json.Marshal來(lái)將結(jié)構(gòu)體數(shù)據(jù)轉(zhuǎn)換為json字符串時(shí),需要注意結(jié)構(gòu)體內(nèi)成員變量的首字母大小寫(xiě)的問(wèn)題,很容易會(huì)掉進(jìn)坑里.
來(lái)看一下這個(gè)例子
package main import ( "encoding/json" "fmt" ) type Student struct { Name string age int } func main() { var s Student = Student { Name: "xiaomo", age: 18, } fmt.Printf("%+v\n", s) res, _ := json.Marshal(s) fmt.Println(string(res)) }
運(yùn)行輸出如下:
$ go run test_json.go
{Name:xiaomo age:18}
{"Name":"xiaomo"}
可以看到轉(zhuǎn)換的json字符串中只包含了Name字段,age字段被忽略了.這是由于在進(jìn)行json解析時(shí),只會(huì)轉(zhuǎn)換結(jié)構(gòu)體能夠?qū)С龅淖侄?首字母大寫(xiě)),其他字段將會(huì)被忽略.
這個(gè)機(jī)制也有個(gè)好處,可以根據(jù)實(shí)際需要,將想要導(dǎo)出字段的名字首字母大寫(xiě),其他字段首字母小寫(xiě)隱藏起來(lái)即可.
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Go http client 連接池不復(fù)用的問(wèn)題
這篇文章主要介紹了Go http client 連接池不復(fù)用的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Go開(kāi)源項(xiàng)目分布式唯一ID生成系統(tǒng)
這篇文章主要為大家介紹了Go開(kāi)源項(xiàng)目分布式唯一ID生成系統(tǒng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06使用Go語(yǔ)言簡(jiǎn)單模擬Python的生成器
這篇文章主要介紹了使用Go語(yǔ)言簡(jiǎn)單模擬Python的生成器,Python的generator是非??岬墓δ?用Go實(shí)現(xiàn)的代碼也較為簡(jiǎn)潔,需要的朋友可以參考下2015-08-08使用goland調(diào)試遠(yuǎn)程代碼的操作步驟
大家都知道如何在goland調(diào)試遠(yuǎn)程代碼嗎?今天小編給大家分享一篇教程幫助大家學(xué)習(xí)goland調(diào)試遠(yuǎn)程代碼的操作步驟,感興趣的朋友跟隨小編一起看看吧2021-06-06go實(shí)現(xiàn)grpc四種數(shù)據(jù)流模式
這篇文章主要為大家介紹了go實(shí)現(xiàn)grpc四種數(shù)據(jù)流模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04Golang中g(shù)orm無(wú)法將字段更新為空值
本文主要介紹了Golang中g(shù)orm無(wú)法將字段更新為空值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05