Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON
在日常工作中,除了需要從 JSON 轉(zhuǎn)化為 Go 的數(shù)據(jù)結(jié)構(gòu)。但往往相反的情況是:我們需要將數(shù)據(jù)以 JSON 字符串的形式發(fā)送到 Web 服務(wù)器。今天我們將學(xué)會如何從一個結(jié)構(gòu)化數(shù)據(jù)編碼為 JSON 。
Json(Javascript Object Nanotation)是一種數(shù)據(jù)交換格式,常用于前后端數(shù)據(jù)傳輸。任意一端將數(shù)據(jù)轉(zhuǎn)換成json 字符串,另一端再將該字符串解析成相應(yīng)的數(shù)據(jù)結(jié)構(gòu),如string類型,strcut對象等。
結(jié)構(gòu)體轉(zhuǎn)為 JSON 格式
比如,我們有如下的結(jié)構(gòu)體:
type Student struct { ? ? Name string ? ? Age int ? ? Address Address } type Address struct { ? ? Road string ? ? Street string ? ? City string ? ? Province string ? ? Country string } Zhang3 := Student{ ?? ??? ?Name: "張三", ?? ??? ?Age: ?18, ?? ??? ?Address: Address{ ?? ??? ??? ?Road: ? ? "renmin south road", ?? ??? ??? ?Street: ? "123 street", ?? ??? ??? ?City: ? ? "cs", ?? ??? ??? ?Province: "hn", ?? ??? ??? ?Country: ?"CN", ?? ??? ?}, ?? ?}
將學(xué)生編碼為 JSON 格式,我們可以使用 JSON 包中的 json.Marshl() 函數(shù):
Info_of_Zhang3, err := json.Marshal(Zhang3) if err == nil { ? ? fmt.Println(string(Info_of_Zhang3)) } else { ? ? fmt.Println(err) ? ? return }
Marshal() 函數(shù)返回編碼后的 JSON (字節(jié)切片)和 error 信息(如果出錯的話)。然后我們可以打印 JSON 字符串。
完整代碼如下:
package main import ( ?? ?"encoding/json" ?? ?"fmt" ) type Student struct { ?? ?Name ? ?string ?? ?Age ? ? int ?? ?Address Address } type Address struct { ?? ?Road ? ? string ?? ?Street ? string ?? ?City ? ? string ?? ?Province string ?? ?Country ?string } func main() { ?? ?Zhang3 := Student{ ?? ??? ?Name: "張三", ?? ??? ?Age: ?18, ?? ??? ?Address: Address{ ?? ??? ??? ?Road: ? ? "renmin south road", ?? ??? ??? ?Street: ? "123 street", ?? ??? ??? ?City: ? ? "cs", ?? ??? ??? ?Province: "hn", ?? ??? ??? ?Country: ?"CN", ?? ??? ?}, ?? ?} ?? ?Info_of_Zhang3, err := json.Marshal(Zhang3) ?? ?if err == nil { ?? ??? ?fmt.Println(string(Info_of_Zhang3)) ?? ?} else { ?? ??? ?fmt.Println(err) ?? ??? ?return ?? ?} }
運(yùn)行代碼,得到如下 JSON 數(shù)據(jù)結(jié)果:
$ go run main.go
{"Name":"張三","Age":18,"Address":{"Road":"renmin south road","Street":"123 street","City":"cs","Province":"hn","Country":"CN"}}
當(dāng)你看 JSON 輸出時,你可能已經(jīng)注意到?jīng)]有縮進(jìn)。如果你想縮進(jìn)輸出并很好地格式化它,你可以使用json. MarshalIndent()函數(shù)。
比如,使用如下語句:
Info_of_Zhang3, err := json.MarshalIndent(Zhang3, "", " ")
函數(shù)解析:第二個參數(shù)指定每行輸出的開頭的字符串。輸出的開頭,第三個參數(shù)指定每行要縮進(jìn)的字符串。此時json.MarshalIndent(Zhang3, "", " ")可以得到如下的輸出:
{ "Name": "張三", "Age": 18, "Address": { "Road": "renmin south road", "Street": "123 street", "City": "cs", "Province": "hn", "Country": "CN" } }
接口轉(zhuǎn)為 JSON 格式
有時您并不希望固定結(jié)構(gòu)中的字段數(shù)量。 相反,您希望能夠在需要的時候添加額外的數(shù)據(jù)。您可以使用空接口來實現(xiàn)這一點,如下所示:
type Student map[string] interface{} type Address map[string] interface{}
使用空接口,可以創(chuàng)建自己的 Student 變量,還可以添加想要的元素,就像這樣:
Zhang3 := Student{ "Name": "張三", "Age": 18, "Address": Address{ "Road": "renmin south road", "Street": "123 street", "City": "cs", "Province": "hn", "Country": "CN", }, "Year": 2022, // 新增學(xué)年 }
完整代碼如下:
package main import ( ?? ?"encoding/json" ?? ?"fmt" ) type Student map[string]interface{} type Address map[string]interface{} func main() { ?? ?Zhang3 := Student{ ?? ??? ?"Name": "張三", ?? ??? ?"Age": ?18, ?? ??? ?"Address": Address{ ?? ??? ??? ?"Road": ? ? "renmin south road", ?? ??? ??? ?"Street": ? "123 street", ?? ??? ??? ?"City": ? ? "cs", ?? ??? ??? ?"Province": "hn", ?? ??? ??? ?"Country": ?"CN", ?? ??? ?}, ?? ??? ?"Year": ? ? ? 2022, // 新增學(xué)年 ?? ??? ?"GraduateAt": 2026, // 畢業(yè)年份 ?? ?} ?? ?InfoOfZhang3, err := json.MarshalIndent(Zhang3, "", " ? ?") ?? ?if err == nil { ?? ??? ?fmt.Println(string(InfoOfZhang3)) ?? ?} else { ?? ??? ?fmt.Println(err) ?? ?} }
代碼輸出結(jié)果為:
{ "Address": { "City": "cs", "Country": "CN", "Province": "hn", "Road": "renmin south road", "Street": "123 street" }, "Age": 18, "GraduateAt": 2026, "Name": "張三", "Year": 2022 }
同時我們能看到輸出的 JSON 中的鍵的順序是按字母排序的。
Marshal() 函數(shù)的原型
我們看一下 Marshal 函數(shù):
func Marshal(v interface{}) ([]byte, error) { ? ?e := newEncodeState() ? ?err := e.marshal(v, encOpts{escapeHTML: true}) ? ?if err != nil { ? ? ? return nil, err ? ?} ? ?buf := append([]byte(nil), e.Bytes()...) ? ?e.Reset() ? ?encodeStatePool.Put(e) ? ?return buf, nil }
函數(shù)可以接收任意類型的接口數(shù)據(jù) v,并轉(zhuǎn)換為字節(jié)數(shù)組類型,返回值就是 JSON 數(shù)據(jù)和錯誤信息;若轉(zhuǎn)換成功,則 err == nil;
在進(jìn)行對象轉(zhuǎn)換為JSON的過程中,會遵循一下幾條原則:
a. 布爾型轉(zhuǎn)換為JSON后仍然是布爾型;
b. 浮點型轉(zhuǎn)換為JSON后里面的常規(guī)數(shù)字;
c. 字符串將以 UTF-8 編碼轉(zhuǎn)化輸出為 Unicode 字符串,將特殊字符轉(zhuǎn)義;
d. 數(shù)組和切片被轉(zhuǎn)換為JSON里面的數(shù)組,[]byte類會被轉(zhuǎn)換為 base64 編碼后的字符串,slice的零值被轉(zhuǎn)換為null;
e. 結(jié)構(gòu)體轉(zhuǎn)換為 JSON 對象,并且只有結(jié)構(gòu)體內(nèi)變量必須首字母大寫,才可被導(dǎo)出的字段轉(zhuǎn)化輸出,而且這些字段會被作為 JSON 對象的字符串索引;
f. 轉(zhuǎn)換一個 map 類型的數(shù)據(jù)結(jié)構(gòu)時,該數(shù)據(jù)的類型必須時 map[string]T ,T 可以是encoding/json 包支持的任意類型。
總結(jié)
本文只是簡單的把 Go 語言常見的結(jié)構(gòu)體和接口轉(zhuǎn)化為 JSON 數(shù)據(jù),其他類型類似,最后給出了編碼的函數(shù) Marshal() 原型, 并簡單進(jìn)行了解釋。
除此之外,encoding/json 包還提供了 Encode() 和 Decode() 函數(shù)用于單一對象的格式轉(zhuǎn)化,而 Marshal() 和 Unmarshal() 函數(shù)工作于多個對象和字節(jié)流上。
其實,本文只是簡單的介紹了 Go 語言和 JSON 數(shù)據(jù)在控制臺的簡單轉(zhuǎn)化,等后續(xù)的文章介紹了文件讀取和寫入時,就可以學(xué)會與 JSON 文件打交道了。敬請期待!
到此這篇關(guān)于Go 轉(zhuǎn) JSON的文章就介紹到這了,更多相關(guān)Go 轉(zhuǎn) JSON內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言中基本數(shù)據(jù)類型的相互轉(zhuǎn)換詳解
Go在不同類型的變量之間賦值時需要顯示轉(zhuǎn)換,不能自動轉(zhuǎn)換。這篇文章主要和大家介紹了Go語言中基本數(shù)據(jù)類型的相互轉(zhuǎn)換,感興趣的小伙伴可以了解一下2022-10-10詳解Golang如何實現(xiàn)節(jié)假日不打擾用戶
這篇文章主要為大家介紹了Golang如何實現(xiàn)節(jié)假日不打擾用戶過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Go語言中使用flag包對命令行進(jìn)行參數(shù)解析的方法
這篇文章主要介紹了Go語言中使用flag包對命令行進(jìn)行參數(shù)解析的方法,文中舉了一個實現(xiàn)flag.Value接口來自定義flag的例子,需要的朋友可以參考下2016-04-04Go語言實現(xiàn)一個簡單生產(chǎn)者消費(fèi)者模型
本文主要介紹了Go語言實現(xiàn)一個簡單生產(chǎn)者消費(fèi)者模型,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12