golang中encoding/json包的實(shí)現(xiàn)
Go 語(yǔ)言通過(guò) encoding/json 包提供了對(duì) JSON 數(shù)據(jù)的強(qiáng)大支持,包括序列化、反序列化、自定義處理、數(shù)組處理、任意結(jié)構(gòu)解析以及流式處理等。
1. 基本使用
1.1 結(jié)構(gòu)體字段與 JSON 的映射
在 Go 中,結(jié)構(gòu)體的字段可以通過(guò) json 標(biāo)簽(JSON Tag)與 JSON 字段進(jìn)行映射。如果不指定 json 標(biāo)簽,默認(rèn)使用結(jié)構(gòu)體字段名的蛇形命名(小寫)作為 JSON 字段名。
type P struct { // 未使用json標(biāo)簽,自動(dòng)根據(jù)字段名稱進(jìn)行綁定
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)簽,序列化時(shí)會(huì)使用結(jié)構(gòu)體字段名作為 JSON 字段名。 - 結(jié)構(gòu)體
Person:Name和Age使用json標(biāo)簽映射為name和age。Address使用-標(biāo)簽,表示不會(huì)被序列化。Sex使用omitempty,當(dāng)字段為空時(shí)不會(huì)被序列化。
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)
// 處理錯(cuò)誤
fmt.Println(string(json1))
// 輸出示例: {"Name":"Jon","Age":20,"Address":"beijing","Sex":"男","Time":"..."}
json2, err := json.Marshal(p2)
// 處理錯(cuò)誤
fmt.Println(string(json2))
// 輸出示例: {"name":"hon","age":20}
// 解碼(反序列化)
var p3 Person
err = json.Unmarshal(json1, &p3)
// 處理錯(cuò)誤
fmt.Printf("%+v\n", p3)
// 輸出: {Name:Jon Age:20 Address: Sex:男}
err = json.Unmarshal(json2, &p3)
// 處理錯(cuò)誤
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 序列化與反序列化
有時(shí)候,默認(rèn)的序列化和反序列化方式無(wú)法滿足需求,這時(shí)可以通過(guò)實(shí)現(xiàn) MarshalJSON 和 UnmarshalJSON 方法來(lái)自定義行為。
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)
// 處理錯(cuò)誤
fmt.Println(string(jsonBytes))
// 輸出: {"Name":"jon","Address":{"state":"beijing"}}
}
Massachusetts結(jié)構(gòu)體通過(guò)自定義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)
// 處理錯(cuò)誤
fmt.Println(string(jonsBytes))
// 輸出: [{"name":"p1","age":22},{"name":"p2","age":23}]
}
JsonArray函數(shù)展示了如何將切片序列化為 JSON 數(shù)組,以及如何進(jìn)行反序列化。
4. 解析任意結(jié)構(gòu)的 JSON 數(shù)據(jù)
在處理來(lái)自外部系統(tǒng)的 JSON 數(shù)據(jù)時(shí),通常無(wú)法提前知道其具體結(jié)構(gòu)。Go 提供了 map[string]interface{} 和 interface{} 來(lái)處理這種情況。
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)
// 處理錯(cuò)誤
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ù)
對(duì)于大型 JSON 數(shù)據(jù),逐行讀寫(流式處理)比一次性加載整個(gè)文件更加高效。Go 提供了 json.Decoder 和 json.Encoder 來(lái)處理流式 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. 時(shí)間類型的序列化與反序列化
在處理包含時(shí)間字段的 JSON 數(shù)據(jù)時(shí),默認(rèn)的序列化格式為 RFC3339。如果需要自定義時(shí)間格式,可以通過(guò)自定義類型實(shí)現(xiàn)。
6.1 自定義時(shí)間格式示例
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] // 去除雙引號(hào)
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)
// 處理錯(cuò)誤
fmt.Println(string(jsonBytes))
// 輸出: {"name":"jon","created_at":"2025-04-03 23:48:31"}
var p2 P5
err = json.Unmarshal(jsonBytes, &p2)
// 處理錯(cuò)誤
fmt.Printf("%+v\n", p2)
// 輸出: {Name:jon CreatedAt:2025-04-03 23:48:31 +0800 CST}
}
CustomTime類型通過(guò)實(shí)現(xiàn)自定義的MarshalJSON和UnmarshalJSON方法,定義了時(shí)間的序列化和反序列化格式。
總結(jié)
Go 語(yǔ)言的 encoding/json 包提供了靈活而強(qiáng)大的工具來(lái)處理 JSON 數(shù)據(jù)。無(wú)論是基本的序列化和反序列化,還是復(fù)雜的自定義行為、數(shù)組處理、任意結(jié)構(gòu)解析以及流式處理,encoding/json 都能很好地滿足需求。理解并掌握這些功能,有助于在開發(fā)中高效地處理各種 JSON 數(shù)據(jù)相關(guān)的任務(wù)。
到此這篇關(guān)于golang中encoding/json包的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang encoding/json包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go實(shí)現(xiàn)HTTP請(qǐng)求轉(zhuǎn)發(fā)的示例代碼
請(qǐng)求轉(zhuǎn)發(fā)是一項(xiàng)核心且常見的功能,本文主要介紹了Go實(shí)現(xiàn)HTTP請(qǐng)求轉(zhuǎn)發(fā)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-05-05
Golang使用crypto/ed25519實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證
本文將深入探討如何在?Golang?中使用?crypto/ed25519?進(jìn)行數(shù)字簽名和驗(yàn)證,我們將從基本原理開始,逐步引導(dǎo)讀者了解生成密鑰對(duì)、進(jìn)行數(shù)字簽名,以及驗(yàn)證簽名的具體過(guò)程,希望對(duì)大家有所幫助2024-02-02
go語(yǔ)言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode1128等價(jià)多米諾骨牌對(duì)的數(shù)量示例詳解,2022-12-12
基于go實(shí)例網(wǎng)絡(luò)存儲(chǔ)協(xié)議詳解
這篇文章主要為大家介紹了基于go實(shí)例網(wǎng)絡(luò)存儲(chǔ)協(xié)議詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Golang?IOT中的數(shù)據(jù)序列化與解析過(guò)程
這篇文章主要介紹了Golang?IOT中的數(shù)據(jù)序列化與解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05

