欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

重學(xué)Go語言之JSON操作詳解

 更新時(shí)間:2023年08月27日 08:25:19   作者:程序員讀書  
JSON的全稱是Javascript?Object?Notation,是一種數(shù)據(jù)結(jié)構(gòu)化交互的標(biāo)準(zhǔn)協(xié)議,這篇文章主要是來和大家介紹一下Go語言中JSON的相關(guān)操作,需要的可以參考下

當(dāng)你想在項(xiàng)目中保存配置時(shí),你會(huì)選擇什么數(shù)據(jù)格式,你可能會(huì)說用yaml或是json,當(dāng)你作為后端要把數(shù)據(jù)返回給前端時(shí),你會(huì)選擇什么數(shù)據(jù)格式,這次我想,一定是json了吧。

關(guān)于在Go語言如何操作JSON,在這篇文章我們來探究一下!

JSON

什么是JSONJSON的全稱是Javascript Object Notation,是一種數(shù)據(jù)結(jié)構(gòu)化交互的標(biāo)準(zhǔn)協(xié)議,非常容易閱讀與編寫,可以作為配置文件保存應(yīng)用的相關(guān)配置信息,也可以作為前后端接口數(shù)據(jù)的格式,比如后端返回給前端這樣的JSON數(shù)據(jù):

{
	"code":404,
	"msg":"Not Found"
}

JSON的數(shù)據(jù)類型

JSON只支持六種數(shù)據(jù)類型,分別是:

  • 數(shù)字(number):有十進(jìn)制和科學(xué)記數(shù)學(xué)兩種表示方式。
  • 字符串(string):使用雙引號(hào)表示的Unicode字符序列。
  • 布爾(bool)true或者false
  • 對(duì)象(object):使用花括號(hào)({})括起來的一個(gè)或多個(gè)鍵值對(duì)(key/value),用逗號(hào)(,)隔開,最后一個(gè)鍵值對(duì)后面不能有逗號(hào),鍵(key)必是雙引號(hào)("")引起來的字符串,而值則可以是任意類型(如:布爾、數(shù)字、對(duì)象、數(shù)組、字符串)。
  • 數(shù)組(array):使用中括號(hào)([])括起來的值的集合,這些值可是任意類型(布爾、數(shù)字、對(duì)象、數(shù)組、字符串)。
  • null:空值。

JSON類型與Go數(shù)據(jù)類型的對(duì)應(yīng)關(guān)系:

  • Go的boolean對(duì)應(yīng)JSON的bool類型
  • Go的整型與浮點(diǎn)型對(duì)應(yīng)JSON的number類
  • Go的map和struct對(duì)應(yīng)JSON的object,map的key必須是字符串
  • Go的切片與數(shù)組對(duì)應(yīng)JSON的array
  • Go的chan與函數(shù)等復(fù)雜的類型不能作為JSON的值

JSON的基本操作

Go語言在encoding/json包中提供了JSON數(shù)據(jù)序列化與反序列化的操作,最簡(jiǎn)單直接就是調(diào)用Marshal把一個(gè)Go的數(shù)據(jù)序列化為一個(gè)JSON數(shù)據(jù)和調(diào)用Unmarshal對(duì)JSON數(shù)據(jù)反序列化。

Marshal

json包的Marshal()函數(shù)用于將數(shù)據(jù)編碼為一個(gè)JSON文本,該函數(shù)的簽名如下所示:

func Marshal(v interface{}) ([]byte, error) 

Marshal()函數(shù)可以接受任意值,并返回JSON化的字節(jié)數(shù)組與一個(gè)error類型:

package main
import (
	"encoding/json"
	"fmt"
)
func main() {
	m := map[string]int{"Go入門": 1, "Go Ation": 2, "Go從入門到精通": 3, "Go高級(jí)編程": 4}
	data, err := json.Marshal(m)
	if err != nil {
		panic(err)
	}
    //轉(zhuǎn)換為string并輸出
	fmt.Println(string(data)) 
}

上面示例程序的運(yùn)行結(jié)果:

{"Go Ation":2,"Go從入門到精通":3,"Go入門":1,"Go高級(jí)編程":4}

MarshalIndent

上面調(diào)用Marshal函數(shù)序列化的數(shù)據(jù)輸出了一行,如果數(shù)據(jù)太長(zhǎng),則不利于我們閱讀,要想輸出的JSON數(shù)據(jù)格式更友好一點(diǎn),可以用MarshalIndent函數(shù),該函數(shù)簽名如下:

func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

相比于Marshal函數(shù),MarshalIndent函數(shù)可以接收一個(gè)prefixindent,用于設(shè)置輸出JSON每一行的前綴和首行縮進(jìn),下面是一個(gè)使用該函數(shù)的例子:

package main
import (
	"encoding/json"
	"fmt"
)
func main() {
	m := map[string]int{"Go入門": 1, "Go Ation": 2, "Go從入門到精通": 3, "Go高級(jí)編程": 4}
    //設(shè)置prefix為空,indent為tab
	data, err := json.MarshalIndent(m, "", "\t")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

設(shè)置了indent參數(shù)后的運(yùn)行結(jié)果:

{
	"Go Ation": 2,
    "Go從入門到精通": 3,
    "Go入門": 1,
    "Go高級(jí)編程": 4
}

json.Unmarshal

json包的Unmarshal()函數(shù)作用與Marshal剛好相反,用于將一個(gè)JSON數(shù)據(jù)格式反序列化到一個(gè)我們定義好的Go類型變量中,該函數(shù)的簽名如下所示:

func Unmarshal(data []byte, v interface{}) error 

下面是一個(gè)反序列化的示例:

package main
import (
	"encoding/json"
	"fmt"
)
type Book struct {
	BookName string `json:"name"`
	Number   int    `json:"num"`
}
func main() {
	jsonStr := `[{"name":"Go入門","num": 1}, {"name":"Go Ation","num": 2}, {"name":"Go從入門到精通","num": 3}, {"name":"Go高級(jí)編程","num": 4}]`
	var books []Book
	err := json.Unmarshal([]byte(jsonStr), &books)
	if err != nil {
		panic(err)
	}
	fmt.Println(books)
}

上面的例子中,我們將一個(gè)JSON反序化到一個(gè)數(shù)組當(dāng)中,而該數(shù)組的元素是一個(gè)自定義的struct類型,在struct中可以通過json tag來定義json的字段名稱。

自定義序列化

如果是自定義的數(shù)據(jù)類型,我們可以實(shí)現(xiàn)Marshaler接口和Unmarshaler接口的方法,這兩個(gè)接口的定義如下:

type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}
type Marshaler interface {
	MarshalJSON() ([]byte, error)
}

當(dāng)調(diào)用Marshal函數(shù)序列化時(shí),會(huì)調(diào)用MarshalJSON()函數(shù),我們可以在該函數(shù)中自定義序列化的邏輯:

package main
import (
	"encoding/json"
	"fmt"
	"strings"
)
type Reason uint8
const (
	Unknown = iota
	Spring
	Summer
	Autumn
	Winter
)
//自定義反序列邏輯
func (r *Reason) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	switch strings.ToLower(s) {
	default:
		*r = Unknown
	case "spring":
		*r = Spring
	case "summer":
		*r = Summer
	case "autumn":
		*r = Autumn
	case "winter":
		*r = Winter
	}
	return nil
}
//自定義序列邏輯
func (r Reason) MarshalJSON() ([]byte, error) {
	var s string
	switch r {
	default:
		s = "unknonw"
	case Spring:
		s = "spring"
	case Summer:
		s = "summer"
	case Autumn:
		s = "autumn"
	case Winter:
		s = "winter"
	}
	return json.Marshal(s)
}
func main() {
	r := []Reason{1, 2, 3, 4}
	data, err := json.Marshal(r)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

上面的代碼中,Reason也實(shí)現(xiàn)了Unmarshaler接口,因此在調(diào)用Unmarshal函數(shù)反序列化時(shí)會(huì)調(diào)用UnmarshalJSON,在該方法中我們可以自定義反序列化的邏輯:

func main() {
	jsonStr := `["winter","spring","test"]`
	var r []Reason
	err := json.Unmarshal([]byte(jsonStr), &r)
	if err != nil {
		panic(err)
	}
	fmt.Println(r)
} 

Encoder與Decoder

調(diào)用Marshal只會(huì)返回一個(gè)字節(jié)數(shù)組,Unmarshal函數(shù)只能傳入一個(gè)字節(jié)數(shù)組,如果我們想將序列化的數(shù)據(jù)寫入到不同的地方(比如保存到一個(gè)文件中),或者想從不同地方讀取JSON數(shù)據(jù)(比如從一個(gè)文件讀取),那么用EncoderDecoder會(huì)更方便。

json.Encoder

NewEncoder函數(shù)可以創(chuàng)建一個(gè)Encoder結(jié)構(gòu)體,NewEncoder函數(shù)接收一個(gè)實(shí)現(xiàn)了io.Writer接口的參數(shù),在序列化后會(huì)調(diào)用io.Writer寫入數(shù)據(jù):

package main
import (
	"encoding/json"
	"os"
)
func main() {
	m := map[string]int{"Go入門": 1, "Go Ation": 2, "Go從入門到精通": 3, "Go高級(jí)編程": 4}
	file, err := os.Create("config.json")
	if err != nil {
		panic(err)
	}
    defer file.Close()
	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "\t")
	err = encoder.Encode(m)
	if err != nil {
		panic(err)
	}
}

上面程序運(yùn)行后,會(huì)把JSON數(shù)據(jù)保存到當(dāng)前目錄的config.json文件當(dāng)中。

json.Decoder

NewDecoder函數(shù)可以創(chuàng)建一個(gè)Decoder結(jié)構(gòu)體,NewDecoder函數(shù)接收一個(gè)實(shí)現(xiàn)了io.Reader接口的參數(shù),也就是說Decoderio.Reader中讀取數(shù)據(jù):

package main
import (
	"encoding/json"
	"fmt"
	"os"
)
func main() {
	file, err := os.Open("config.json")
	if err != nil {
		panic(err)
	}
	defer file.Close()
	decoder := json.NewDecoder(file)
	var m map[string]int
	err = decoder.Decode(&m)
	if err != nil {
		panic(err)
	}
	fmt.Println(m)
}

小結(jié)

JSON是一種非常通用的數(shù)據(jù)格式,經(jīng)常被用于前后端api接口的數(shù)據(jù)通信,而Go語言在標(biāo)準(zhǔn)庫encoding/json包中為JSON數(shù)據(jù)的編碼與反編碼提供非常好的支持。

好了,相信看完這篇文章,你應(yīng)該掌握了以下幾點(diǎn)了吧:

  • 什么是JSON
  • 如何序列化與反序列化JSON數(shù)據(jù)
  • 如何自定義序列化過程
  • json.Encoder與json.Decoder的使用

到此這篇關(guān)于重學(xué)Go語言之JSON操作詳解的文章就介紹到這了,更多相關(guān)Go JSON內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang套接字的實(shí)現(xiàn)

    golang套接字的實(shí)現(xiàn)

    Go語言中通過標(biāo)準(zhǔn)庫net實(shí)現(xiàn)套接字編程,涵蓋了TCP和UDP兩種網(wǎng)絡(luò)類型,通過這些基本概念和實(shí)際代碼示例,可以幫助理解和掌握Go語言中的套接字編程
    2024-10-10
  • 五步讓你成為GO 語言高手

    五步讓你成為GO 語言高手

    本文給大家介紹的這里是GO程序員的五個(gè)進(jìn)化階段,從最開始的菜逼到最終的布道者,附上各種示例,一步步走向大神之路,推薦給小伙伴們,有需要的朋友可以參考下
    2015-03-03
  • 在Golang中使用iota案例詳解

    在Golang中使用iota案例詳解

    在Go語言中,iota是一個(gè)預(yù)定義的標(biāo)識(shí)符,用于在常量聲明中生成連續(xù)的遞增值,iota的值從0開始,每次在常量聲明中使用時(shí)遞增,本就給大家講解一下Golang中iota的使用案例,感興趣的同學(xué)跟著小編一起來看看吧
    2023-07-07
  • Go語言輕松實(shí)現(xiàn)郵件發(fā)送通知功能的完全指南

    Go語言輕松實(shí)現(xiàn)郵件發(fā)送通知功能的完全指南

    在現(xiàn)代 Web 應(yīng)用中,郵件通知是一個(gè)不可或缺的功能,本文將深入解析一個(gè)基于 Go 語言 smtp 協(xié)議和 email 庫的郵件發(fā)送工具,需要的可以了解下
    2025-04-04
  • Go gin框架處理panic的方法詳解

    Go gin框架處理panic的方法詳解

    本文我們介紹下recover在gin框架中的應(yīng)用, 首先,在golang中,如果在子協(xié)程中遇到了panic,那么主協(xié)程也會(huì)被終止,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Go channel如何批量讀取數(shù)據(jù)

    Go channel如何批量讀取數(shù)據(jù)

    本文將展示一個(gè)從 Go channel 中批量讀取數(shù)據(jù),并批量發(fā)送到 Kafka 和批量寫入網(wǎng)絡(luò)數(shù)據(jù)的示例,文中的示例代碼講解詳細(xì),有需要的可以參考下
    2024-10-10
  • Go語言中的Iota關(guān)鍵字

    Go語言中的Iota關(guān)鍵字

    這篇文章介紹了Go語言中的Iota關(guān)鍵字,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • Go中sync.Mutex 加鎖失效的問題解決

    Go中sync.Mutex 加鎖失效的問題解決

    sync.Mutex是Go標(biāo)準(zhǔn)庫中常用的一個(gè)排外鎖,本文主要介紹了Go中sync.Mutex 加鎖失效的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Go web入門Go pongo2模板引擎

    Go web入門Go pongo2模板引擎

    這篇文章主要為大家介紹了Go web編程入門Go pongo2模板引擎使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Golang中調(diào)用deepseekr1的教程詳解

    Golang中調(diào)用deepseekr1的教程詳解

    這篇文章主要為大家詳細(xì)介紹了Golang中調(diào)用deepseekr1的相關(guān)教程,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解下
    2025-02-02

最新評(píng)論