『Go 內建庫第一季:json』
WOMEN_WHO_GO_SEATTLE.png
大家好,我叫謝偉,是一名程式設計師。
近期我會持續更新內建庫的學習筆記,主要參考的是文件 godoc 和 內建庫的原始碼
在日常開發過程中,使用最頻繁的當然是內建庫,無數的開源專案,無不是在內建庫的基礎之上進行衍生、開發,所以其實是有很大的必要進行梳理學習。
本節的主題:內建庫 json
大綱:
自己總結的使用方法
官方支援的API
學到了什麼
自己總結的用法
既然是 json 操作,那麼核心應該是包括兩個方面:
序列化:go 資料型別轉換為 json
反序列化:json 轉換為 go 資料型別
對應的方法:
func Marshal(v interface{}) ([]byte, error)
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error
具體如何使用呢?
布林型別
func boolToJson(ok bool) []byte { jsonResult, _ := json.Marshal(ok) return jsonResult }func jsonToBool(value []byte) bool { var goResult bool json.Unmarshal(value, &goResult) return goResult }func main(){ fmt.Println(string(boolToJson(1 == 1))) fmt.Println(jsonToBool([]byte(`true`))) } >>truetrue
數值型
func intToJson(value int) []byte { jsonInt, _ := json.Marshal(value) return jsonInt }func main(){ fmt.Println(string(intToJson(12))) } >> 12
結構體
結構體 轉換為 json
type Info struct { Name string `json:"name,omitempty"` Age int `json:"age,string"` City string `json:"city_shanghai"` Company string `json:"-"` } func (i Info) MarshalOp() []byte { jsonResult, _ := json.Marshal(i) return jsonResult } func main(){ var info Info info = Info{ Name: "XieWei", Age: 100, City: "shangHai", Company: "Only Me", } fmt.Println(string(info.MarshalOp())) var otherInfo Info otherInfo.Name = "" otherInfo.Age = 20 otherInfo.City = "BeiJing" otherInfo.Company = "Only You" fmt.Println(string(otherInfo.MarshalOp())) } >> {"name":"XieWei","age":"100","city_shanghai":"shangHai"} {"age":"20","city_shanghai":"BeiJing"}
還記得我們之間講的 反射章節 結構體的 tag 嗎?
info 結構體的 tag
omitempty 表示該欄位為空時,不序列化
-
表示忽略該欄位json 內定義了該欄位序列化時顯示的欄位,比如 Name 最後序列化 為 name;比如 City 最後序列化為 city_shanghai
json 內還可以轉換型別,比如 age 原本 int 型別,最後轉化為 string 型別
json 轉換為 結構體:
func UnMarshalExample(value []byte) (result Info) { json.Unmarshal(value, &result) return result }func main(){ fmt.Println(UnMarshalExample([]byte(`{"name":"xieWei", "age": "20", "city_shanghai": "GuangDong"}`))) } >> {xieWei 20 GuangDong }
好,至此,我們常用的 json 操作就這些,主要兩個方面:Marshal 和 UnMarshal
大概講述了下 結構體的 tag 的作用:
比如如何定義欄位名稱
比如如何忽略欄位
比如如何更改型別
比如如何零值忽略
官方文件
列舉幾個再常用的:
func Valid(data []byte) bool
type Marshaler 介面,可以自己定義序列化的返回值
type Unmarshaler 介面,可以自己定義反序列化的返回值
Valid
判斷是否是有效的 json 格式的資料
func main(){ fmt.Println(json.Valid([]byte(`{"name":1, 2}`))) } >>false
表示不是標準的 json 格式的資料
Marshaler 介面,需要實現 MarshalJSON 方法
自定義序列化返回值
type Marshaler interface { MarshalJSON() ([]byte, error) }
type SelfMarshal struct { Name string Age int City string } func (self SelfMarshal) MarshalJSON() ([]byte, error) { result := fmt.Sprintf("name:--%s,age:--%d,city:--%s", self.Name, self.Age, self.City) if !json.Valid([]byte(result)) { fmt.Println("invalid") return json.Marshal(result) } return []byte(result), nil} func main(){ var self = SelfMarshal{} self.Age = 20 self.Name = "XieWei" self.City = "HangZhou" selfJsonMarshal, err := json.Marshal(self) fmt.Println(err, string(selfJsonMarshal)) } >> <nil> "name:--XieWei,age:--20,city:--HangZhou"
返回了自定義的序列化的格式
type jsonTime time.Time//實現它的json序列化方法func (this jsonTime) MarshalJSON() ([]byte, error) { var stamp = fmt.Sprintf(""%s"", time.Time(this).Format("2006-01-02 15:04:05")) return []byte(stamp), nil } type Test struct { Date jsonTime `json:"date"` Name string `json:"name"` State bool `json:"state"` } func main(){ var t = Test{} t.Date = jsonTime(time.Now()) t.Name = "Hello World" t.State = true body, _ := json.Marshal(t) fmt.Println(string(body)) } >> {"date":"2018-11-06 22:23:19","name":"Hello World","state":true}
返回了自定義的序列化格式資料
總結
友好的 API
日常的序列化反序列化,內建的庫其實已經滿足要求,但是對於複雜的巢狀的資料型別,想要獲取某個欄位的值則相當費勁
所以衍生了各種各樣的號稱高效能的 json 解析庫
|
收穫:
可以自己定義序列化、反序列化的格式
可以檢測 是否符合 json 型別
func (self SelfMarshal) MarshalJSON() ([]byte, error) { result := fmt.Sprintf("name:--%s,age:--%d,city:--%s", self.Name, self.Age, self.City) return []byte(result), nil }
上文程式碼會報錯,為什麼?因為不是標準 json 格式的資料。
所以通常建議這麼做:
func (self SelfMarshal) MarshalJSON() ([]byte, error) { result := fmt.Sprintf("name:--%s,age:--%d,city:--%s", self.Name, self.Age, self.City) if !json.Valid([]byte(result)) { fmt.Println("invalid") return json.Marshal(result) } return []byte(result), nil}
即將字串 marshal 處理。
作者:謝小路
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4301/viewspace-2819955/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 『Go 內建庫第一季:time』Go
- 『Go 內建庫第一季:error』GoError
- 『Go 內建庫第一季:reflect』Go
- 『Go 內建庫第一季:strings』Go
- 『Go 內建庫第一季:strconv』Go
- GO語言————6.5 內建函式Go函式
- Go語言實戰(三)- 內建容器Go
- 一個非常棒的Go-Json解析庫GoJSON
- json-to-goJSONGo
- 一文吃透 Go 內建 RPC 原理GoRPC
- go 的 json 標準庫有接班人了GoJSON
- 預計在 Go 1.18 中內建泛型Go泛型
- 粗談Python內建庫itertoolsPython
- 跟著老貓來搞GO-內建容器MapGo
- 認真一點學 Go:9. 內建集合 - mapGo
- Go之json資料GoJSON
- idea內建資料庫DataGrip + 索引Idea資料庫索引
- 認真一點學 Go:7. 內建集合 - 陣列Go陣列
- 如何用Go構建GoGo
- Go json 踩坑記錄GoJSON
- idea內建資料庫 + sql語句庫表操作Idea資料庫SQL
- cJSON:構建JSONJSON
- Go構建遇到cgo動態庫時解決方案Go
- python演算法常用技巧與內建庫Python演算法
- Python內建庫:getpass(密碼輸入工具)Python密碼
- Go - 如何解析 JSON 資料?GoJSON
- Go JSON編碼與解碼?GoJSON
- Go語言RESTful JSON API建立GoRESTJSONAPI
- go語言json的使用技巧GoJSON
- Go 結構體 Json 互轉Go結構體JSON
- go restful api server 內建程式碼生成器,助力快速開發GoRESTAPIServer
- 資料庫為何不建議部署在Docker容器內資料庫Docker
- Python中內建資料庫!SQLite使用指南! ⛵Python資料庫SQLite
- Python內建庫:pathlib(檔案路徑操作)Python
- 通過Go來分析和建立JSONGoJSON
- Go語言轉換JSON資料GoJSON
- 清華尹成帶你實戰GO案例(10)Go JSON支援GoJSON
- 手工建庫與dbca建庫