Go語言結構體鏈式程式設計與JSON序列化

尹正杰發表於2024-07-31

                                              作者:尹正傑

版權宣告:原創作品,謝絕轉載!否則將追究法律責任。

目錄
  • 一.json概述
  • 二.結構體的序列化JSON格式
  • 三.結構體的反序列化JSON格式
  • 四.結構體標籤(tag)
    • 1 結構體標籤(tag)概述
    • 2 結構體標籤(tag)案例
  • 五.鏈式程式設計

一.json概述

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。

JSON鍵值對是用來儲存JS物件的一種方式,鍵/值對組合中的鍵名寫在前面並用雙引號""包裹,使用冒號:分隔,然後緊接著值;多個鍵值之間使用英文,分隔。

二.結構體的序列化JSON格式

package main

import (
	"encoding/json"
	"fmt"
)

// Book 書籍結構體
type Book struct {
	ID   int
	Name string
}

// Auther 作者
type Auther struct {
	Auther string
	Alias  string
	Books  []*Book
}

func main() {

	// 定義作者
	auther := &Auther{
		Auther: "楊振東",
		Alias:  "辰東",
		Books:  make([]*Book, 0, 200),
	}

	// 定義書籍
	b1 := &Book{1, "《完美世界》"}
	b2 := &Book{2, "《遮天》"}
	b3 := &Book{3, "《聖墟》"}

	// 將資料加入到作者的書籍切片中
	auther.Books = append(auther.Books, b1)
	auther.Books = append(auther.Books, b2)
	auther.Books = append(auther.Books, b3)

	//JSON序列化:結構體-->JSON格式的字串
	data, err := json.Marshal(auther)
	if err != nil {
		fmt.Printf("%v序列化JSON格式失敗\n", auther)
		return
	}

	fmt.Printf("JSON格式轉換前: %#v\n", auther)
	fmt.Printf("JSON格式轉換後: %s\n", data)

}

三.結構體的反序列化JSON格式

package main

import (
	"encoding/json"
	"fmt"
)

// Book 書籍結構體
type Book struct {
	ID   int
	Name string
}

// Auther 作者
type Auther struct {
	Auther string
	Alias  string
	Books  []*Book
}

func main() {

	str := `{"Auther":"楊振東","Alias":"辰東","Books":[{"ID":1,"Name":"《完美世界》"},{"ID":2,"Name":"《遮天》"},{"ID":3,"Name":"《聖墟》"}]}`

	auther := &Auther{}

	//JSON反序列化:將JSON格式的字串轉換為結構體
	err := json.Unmarshal([]byte(str), auther)
	if err != nil {
		fmt.Printf("JSON反序列化為結構體失敗: err =%v\n", err)
		return
	}

	fmt.Printf("auther = %#v\n", auther)

	fmt.Printf("'%s'筆名是'%s',代表作有:%q\n", auther.Auther, auther.Alias, auther.Books)
}

四.結構體標籤(tag)

1 結構體標籤(tag)概述

Tag是結構體的元資訊,可以在執行的時候透過反射的機制讀取出來。

Tag在結構體欄位的後方定義,由一對反引號包裹起來,具體的格式如下:
	`key1:"value1" key2:"value2"`
	
結構體tag由一個或多個鍵值對組成。鍵與值使用冒號分隔,值用雙引號括起來。同一個結構體欄位可以設定多個鍵值對tag,不同的鍵值對之間使用空格分隔。

注意事項: 
	為結構體編寫Tag時,必須嚴格遵守鍵值對的規則。結構體標籤的解析程式碼的容錯能力很差,一旦格式寫錯,編譯和執行時都不會提示任何錯誤,透過反射也無法正確取值。例如不要在key和value之間新增空格。

2 結構體標籤(tag)案例

package main

import (
	"encoding/json"
	"fmt"
)

type Teacher struct {
	// 透過指定tag實現json序列化該欄位時的key
	Name  string   `json:"name"`
	Hobby []string `json:"hobby"`

	// json序列化是預設使用欄位名作為key
	Blog string

	// 小寫字母屬於私有屬性,不能被json包訪問
	age   int
	skill string `json:"skill"`
}

func main() {

	hobby := []string{"K8S", "打遊戲", "旅遊"}

	t1 := &Teacher{
		Name:  "周敏",
		age:   18,
		Hobby: hobby,
		skill: "K8S",
		Blog:  "https://www.cnblogs.com/yinzhengjie",
	}

	fmt.Printf("結構體源資料 : %#v\n", t1)

	// JSON序列化:結構體-->JSON格式的字串
	data, err := json.Marshal(t1)
	if err != nil {
		fmt.Println("json marshal failed!")
		return
	}

	fmt.Printf("JSON資料: %s\n", data)

}

五.鏈式程式設計

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

/*
	鏈式操作:
		   這種連續使用"."的方式調方法我們稱之為"鏈式操作"。
	鏈式原理:
	     每一次執行完方法之後返回操作的物件本身。
*/

type Teacher struct {
	Name string `json:"name"`
	Age  uint8  `json:"age"`
	Blog string `json:"blog"`
}

func (t Teacher) Learn() Teacher {
	fmt.Printf("%s熱愛學習\n", t.Name)
	return t
}

func (t Teacher) WriteBolog() Teacher {
	fmt.Printf("%s熱愛寫部落格,部落格地址: %s\n", t.Name, t.Blog)
	return t
}

func (t Teacher) Marshal(filePath string) Teacher {

	// 以只寫的模式開啟檔案
	file, _ := os.OpenFile(filePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)

	defer file.Close()

	// JSON序列化:結構體-->JSON格式的字串
	data, _ := json.Marshal(t)

	fmt.Printf("JSON資料: %s\n", data)

	// 寫入位元組切片資料
	file.Write([]byte(data))

	return t
}

func main() {

	t1 := Teacher{
		Name: "JasonYin",
		Age:  20,
		Blog: "https://www.cnblogs.com/yinzhengjie",
	}

	t1.Learn().WriteBolog().Marshal("blog.txt")

}

相關文章