亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

重學Go語言之JSON操作詳解

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

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

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

JSON

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

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

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

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

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

JSON類型與Go數(shù)據(jù)類型的對應關系:

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

JSON的基本操作

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

Marshal

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

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

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

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

上面示例程序的運行結果:

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

MarshalIndent

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

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

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

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

設置了indent參數(shù)后的運行結果:

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

json.Unmarshal

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

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

下面是一個反序列化的示例:

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高級編程","num": 4}]`
	var books []Book
	err := json.Unmarshal([]byte(jsonStr), &books)
	if err != nil {
		panic(err)
	}
	fmt.Println(books)
}

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

自定義序列化

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

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

當調(diào)用Marshal函數(shù)序列化時,會調(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也實現(xiàn)了Unmarshaler接口,因此在調(diào)用Unmarshal函數(shù)反序列化時會調(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只會返回一個字節(jié)數(shù)組,Unmarshal函數(shù)只能傳入一個字節(jié)數(shù)組,如果我們想將序列化的數(shù)據(jù)寫入到不同的地方(比如保存到一個文件中),或者想從不同地方讀取JSON數(shù)據(jù)(比如從一個文件讀取),那么用EncoderDecoder會更方便。

json.Encoder

NewEncoder函數(shù)可以創(chuàng)建一個Encoder結構體,NewEncoder函數(shù)接收一個實現(xiàn)了io.Writer接口的參數(shù),在序列化后會調(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高級編程": 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)
	}
}

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

json.Decoder

NewDecoder函數(shù)可以創(chuàng)建一個Decoder結構體,NewDecoder函數(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)
}

小結

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

好了,相信看完這篇文章,你應該掌握了以下幾點了吧:

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

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

相關文章

  • Go模板template用法詳解

    Go模板template用法詳解

    這篇文章主要介紹了Go標準庫template模板用法詳解;包括GO模板注釋,作用域,語法,函數(shù)等知識,需要的朋友可以參考下
    2022-04-04
  • 最新版Golang?pprof使用詳解(引入、抓取、分析,圖文結合)

    最新版Golang?pprof使用詳解(引入、抓取、分析,圖文結合)

    這篇文章主要介紹了最新版Golang?pprof使用詳解包括引入、抓取、分析,圖文結合,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-08-08
  • Golang并發(fā)操作中常見的讀寫鎖詳析

    Golang并發(fā)操作中常見的讀寫鎖詳析

    Golang中的鎖機制主要包含互斥鎖和讀寫鎖互斥鎖互斥鎖是傳統(tǒng)并發(fā)程序對共享資源進行控制訪問的主要手段,這篇文章主要給大家介紹了關于Golang并發(fā)操作中常見的讀寫鎖的相關資料,需要的朋友可以參考下
    2021-08-08
  • go HTTP2 的頭部壓縮算法hpack實現(xiàn)詳解

    go HTTP2 的頭部壓縮算法hpack實現(xiàn)詳解

    這篇文章主要為大家介紹了go HTTP2 的頭部壓縮算法hpack實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Golang中錯誤處理機制詳解

    Golang中錯誤處理機制詳解

    平時在項目開發(fā)過程中少不了對錯誤的處理,一個好用的系統(tǒng)首先要確保其健壯性,不能經(jīng)常發(fā)生錯誤就卡死之類的情況,為了讓我們的程序更加健壯,我們就需要知道golang里的錯誤處理機制是怎么樣的,這篇文章帶大家一起學習,需要的朋友跟著小編一起來看看吧
    2024-05-05
  • Go語言數(shù)據(jù)庫編程GORM 的基本使用詳解

    Go語言數(shù)據(jù)庫編程GORM 的基本使用詳解

    GORM是Go語言流行的ORM框架,封裝database/sql,支持自動遷移、關聯(lián)、事務等,提供CRUD、條件查詢、鉤子函數(shù)、日志等功能,簡化數(shù)據(jù)庫操作,提升開發(fā)效率,本文給大家介紹Go語言GORM使用,感興趣的朋友一起看看吧
    2025-06-06
  • Go創(chuàng)建一個包并使用(導入本地包和注意事項)

    Go創(chuàng)建一個包并使用(導入本地包和注意事項)

    有時候需要自己寫一個包方便多次使用,但是在導入自己寫的包時遇到了問題,本文主要介紹了Go創(chuàng)建一個包并使用(導入本地包和注意事項),感興趣的可以了解一下
    2023-11-11
  • Go使用TimerController解決timer過多的問題

    Go使用TimerController解決timer過多的問題

    多路復用,實際上Go底層也是一種多路復用的思想去實現(xiàn)的timer,但是它是底層的timer,我們需要解決的問題就過多的timer問題!本文給大家介紹了Go使用TimerController解決timer過多的問題,需要的朋友可以參考下
    2024-12-12
  • golang類型轉換之interface轉字符串string簡單示例

    golang類型轉換之interface轉字符串string簡單示例

    在我們使用Golang進行開發(fā)過程中,總是繞不開對字符或字符串的處理,這篇文章主要給大家介紹了關于golang類型轉換之interface轉字符串string的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • Go設計模式之代理模式圖文詳解

    Go設計模式之代理模式圖文詳解

    這篇文章將通過圖文講解給大家詳細的介紹一下Go代理模式,代理模式是一種結構型設計模式,代理控制著對于原對象的訪問, 并允許在將請求提交給對象前后進行一些處理,感興趣的同學跟著小編一起來看看吧
    2023-07-07

最新評論