golang中encoding/json包的實現(xiàn)
Go 語言通過 encoding/json
包提供了對 JSON 數(shù)據(jù)的強大支持,包括序列化、反序列化、自定義處理、數(shù)組處理、任意結(jié)構(gòu)解析以及流式處理等。
1. 基本使用
1.1 結(jié)構(gòu)體字段與 JSON 的映射
在 Go 中,結(jié)構(gòu)體的字段可以通過 json
標(biāo)簽(JSON Tag)與 JSON 字段進行映射。如果不指定 json
標(biāo)簽,默認使用結(jié)構(gòu)體字段名的蛇形命名(小寫)作為 JSON 字段名。
type P struct { // 未使用json標(biāo)簽,自動根據(jù)字段名稱進行綁定 Name string Age int Address string Sex string Time time.Time } type Person struct { Name string `json:"name"` Age int `json:"age"` Address string `json:"-"` Sex string `json:"sex,omitempty"` }
- 結(jié)構(gòu)體
P
:未定義json
標(biāo)簽,序列化時會使用結(jié)構(gòu)體字段名作為 JSON 字段名。 - 結(jié)構(gòu)體
Person
:Name
和Age
使用json
標(biāo)簽映射為name
和age
。Address
使用-
標(biāo)簽,表示不會被序列化。Sex
使用omitempty
,當(dāng)字段為空時不會被序列化。
1.2 序列化與反序列化
func main() { p1 := P{ Name: "Jon", Age: 20, Address: "beijing", Sex: "男", Time: time.Now(), } p2 := Person{ Name: "hon", Age: 20, Address: "beijing", Sex: "", } // 編碼(序列化) json1, err := json.Marshal(p1) // 處理錯誤 fmt.Println(string(json1)) // 輸出示例: {"Name":"Jon","Age":20,"Address":"beijing","Sex":"男","Time":"..."} json2, err := json.Marshal(p2) // 處理錯誤 fmt.Println(string(json2)) // 輸出示例: {"name":"hon","age":20} // 解碼(反序列化) var p3 Person err = json.Unmarshal(json1, &p3) // 處理錯誤 fmt.Printf("%+v\n", p3) // 輸出: {Name:Jon Age:20 Address: Sex:男} err = json.Unmarshal(json2, &p3) // 處理錯誤 fmt.Printf("%+v\n", p3) // 輸出: {Name:hon Age:20 Address: Sex:} }
json.Marshal
:將 Go 結(jié)構(gòu)體序列化為 JSON 字符串。json.Unmarshal
:將 JSON 字符串反序列化為 Go 結(jié)構(gòu)體。
2. 自定義 JSON 序列化與反序列化
有時候,默認的序列化和反序列化方式無法滿足需求,這時可以通過實現(xiàn) MarshalJSON
和 UnmarshalJSON
方法來自定義行為。
2.1 自定義類型示例
type Massachusetts struct { Name string } type P3 struct { Name string Address *Massachusetts } // 自定義 MarshalJSON 方法 func (m *Massachusetts) MarshalJSON() ([]byte, error) { return json.Marshal(struct { State string `json:"state"` }{ State: m.Name, }) } func Customize() { address := Massachusetts{Name: "beijing"} p := P3{ Name: "jon", Address: &address, } // 編碼 jsonBytes, err := json.Marshal(p) // 處理錯誤 fmt.Println(string(jsonBytes)) // 輸出: {"Name":"jon","Address":{"state":"beijing"}} }
Massachusetts
結(jié)構(gòu)體通過自定義MarshalJSON
方法,將Name
字段序列化為state
字段。
3. 處理 JSON 數(shù)組
Go 中的切片(Slice)和數(shù)組(Array)可以很方便地序列化為 JSON 數(shù)組,反向亦然。
3.1 JSON 數(shù)組示例
type P4 struct { Name string `json:"name"` Age int `json:"age"` } func JsonArray() { people := []P4{ {Name: "p1", Age: 22}, {Name: "p2", Age: 23}, } jonsBytes, err := json.Marshal(people) // 處理錯誤 fmt.Println(string(jonsBytes)) // 輸出: [{"name":"p1","age":22},{"name":"p2","age":23}] }
JsonArray
函數(shù)展示了如何將切片序列化為 JSON 數(shù)組,以及如何進行反序列化。
4. 解析任意結(jié)構(gòu)的 JSON 數(shù)據(jù)
在處理來自外部系統(tǒng)的 JSON 數(shù)據(jù)時,通常無法提前知道其具體結(jié)構(gòu)。Go 提供了 map[string]interface{}
和 interface{}
來處理這種情況。
4.1 任意結(jié)構(gòu) JSON 示例
func JsonAny() { jsonString := `{ "name":"p1", "Age":21, "email":"1.@qq.com" }` var m map[string]interface{} err := json.Unmarshal([]byte(jsonString), &m) // 處理錯誤 fmt.Printf("%+v\n", m) // 輸出: map[Age:21 email:1.@qq.com name:p1] }
JsonAny
函數(shù)展示了如何將任意結(jié)構(gòu)的 JSON 字符串解析為map[string]interface{}
,方便后續(xù)操作。
5. 流式處理 JSON 數(shù)據(jù)
對于大型 JSON 數(shù)據(jù),逐行讀寫(流式處理)比一次性加載整個文件更加高效。Go 提供了 json.Decoder
和 json.Encoder
來處理流式 JSON 數(shù)據(jù)。
5.1 使用json.Decoder解碼流式 JSON
func JsonNewDecoder() { jsonData := `{"name":"John", "age":23}` reader := strings.NewReader(jsonData) decoder := json.NewDecoder(reader) var p P4 if err := decoder.Decode(&p); err != nil { fmt.Println(err) } fmt.Printf("%+v\n", p) // 輸出: {Name:John Age:23} }
JsonNewDecoder
函數(shù)展示了如何使用json.Decoder
從io.Reader
中逐行讀取和解析 JSON 數(shù)據(jù)。
5.2 使用json.Encoder編碼流式 JSON
func JsonNewEncoder() { p := P4{Name: "p1", Age: 22} writer := &strings.Builder{} encoder := json.NewEncoder(writer) if err := encoder.Encode(&p); err != nil { fmt.Println(err) } fmt.Println(writer.String()) // 輸出: {"name":"p1","age":22} }
JsonNewEncoder
函數(shù)展示了如何使用json.Encoder
將 Go 數(shù)據(jù)結(jié)構(gòu)流式寫入io.Writer
。
6. 時間類型的序列化與反序列化
在處理包含時間字段的 JSON 數(shù)據(jù)時,默認的序列化格式為 RFC3339。如果需要自定義時間格式,可以通過自定義類型實現(xiàn)。
6.1 自定義時間格式示例
type CustomTime time.Time func (ct CustomTime) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"%s\"", time.Time(ct).Format("2006-01-02 15:04:05"))), nil } func (ct *CustomTime) UnmarshalJSON(b []byte) error { str := string(b) str = str[1 : len(str)-1] // 去除雙引號 t, err := time.Parse("2006-01-02 15:04:05", str) if err != nil { return err } *ct = CustomTime(t) return nil } type P5 struct { Name string `json:"name"` CreatedAt CustomTime `json:"created_at"` } func CustomTimeExample() { p := P5{ Name: "jon", CreatedAt: CustomTime(time.Now()), } jsonBytes, err := json.Marshal(p) // 處理錯誤 fmt.Println(string(jsonBytes)) // 輸出: {"name":"jon","created_at":"2025-04-03 23:48:31"} var p2 P5 err = json.Unmarshal(jsonBytes, &p2) // 處理錯誤 fmt.Printf("%+v\n", p2) // 輸出: {Name:jon CreatedAt:2025-04-03 23:48:31 +0800 CST} }
CustomTime
類型通過實現(xiàn)自定義的MarshalJSON
和UnmarshalJSON
方法,定義了時間的序列化和反序列化格式。
總結(jié)
Go 語言的 encoding/json
包提供了靈活而強大的工具來處理 JSON 數(shù)據(jù)。無論是基本的序列化和反序列化,還是復(fù)雜的自定義行為、數(shù)組處理、任意結(jié)構(gòu)解析以及流式處理,encoding/json
都能很好地滿足需求。理解并掌握這些功能,有助于在開發(fā)中高效地處理各種 JSON 數(shù)據(jù)相關(guān)的任務(wù)。
到此這篇關(guān)于golang中encoding/json包的實現(xiàn)的文章就介紹到這了,更多相關(guān)golang encoding/json包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在 Golang 中實現(xiàn)一個簡單的Http中間件過程詳解
本文在go web中簡單的實現(xiàn)了中間件的機制,這樣帶來的好處也是顯而易見的,當(dāng)然社區(qū)也有一些成熟的 middleware 組件,包括 Gin 一些Web框架中也包含了 middleware 相關(guān)的功能,具體內(nèi)容詳情跟隨小編一起看看吧2021-07-07關(guān)于Golang變量初始化/類型推斷/短聲明的問題
這篇文章主要介紹了關(guān)于Golang變量初始化/類型推斷/短聲明的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02