參考文章:
go 官方package: https://blog.golang.org/json
特別好的文章:理解 Go 中的 JSON
JSON是一種輕量級的數據交換格式,常用在前後端數據交換,go的 encoding/json 提供了對json的支持
一、序列化
GO提供了 Marshal 方法:Go Struct轉換爲JSON對象,函數簽名:
func Marshal(v interface{}) ([]byte, error)
舉例:
type Person struct {
Name string
Gender string
Age uint32
}
// 默認初始化
p := Person{"a", "male", 23}
fmt.Println(p)
fmt.Printf("%v\n", p) //{a male 23}
// 指定成員初始化
p1 := Person{Name: "wsq", Gender: "male"}
fmt.Println(p1) //{wsq male 0}
// 序列化
b, _ := json.Marshal(p)
fmt.Println(string(b)) //{"Name":"a","Gender":"male","Age":23}
}
- 只支持struct中導出的field才能被序列化,即
首字母大寫的field
- GO中不是所有類型都支持序列化,其中key只支持
string
- 無法對
channel,complex,function
序列化 - 數據中如存在循環引用,不支持序列化,因爲會遞歸。
pointer
序列化後是其指向的值或者是nil
Struct Tag
指定 JSON filed name
序列化後的json串中的name
一般爲小寫,我們通過struct tag
實現
指定field爲empty
使用omitempty
告訴Marshal函數,如field對應類型爲zero-value,那麼序列化的json對象中不包含此field
跳過field
僅使用"-"
表示跳過指定的field,保護某些字段不被序列化
type Person struct {
Name string `json:"name"`
Gender string `json:"gender"`
Age uint32 `json:"age,omitempty"`
Passwd string `json:"-"`
}
// 默認初始化
p := Person{"a", "male", 23, "mimi"}
fmt.Println(p)
fmt.Printf("%v\n", p) //{a male 23}
// 指定成員初始化
p1 := Person{Name: "wsq", Gender: "male"}
fmt.Println(p1) //{wsq male 0}
// 序列化
b, _ := json.Marshal(p)
fmt.Println(string(b)) //{"Name":"a","Gender":"male","Age":23}
// 反序列化
var pp Person
err := json.Unmarshal(b, &pp)
if err != nil {
errors.New("unmarshal error")
}
fmt.Printf("%T, %v\n", pp, pp)
// Struct Tag
// 指定JSON的field name
c, _ := json.Marshal(p)
fmt.Println(string(c)) //{"name":"a","gender":"male","age":23}
// 指定field是empty時的行爲
d, _ := json.Marshal(p1)
fmt.Println(string(d)) //{"name":"wsq","gender":"male"}
// 跳過指定field
importPerson := Person{Name: "wsq", Passwd: "password"}
importPersonMar, _ := json.Marshal(importPerson)
fmt.Println(string(importPersonMar)) //{"name":"wsq","gender":""}
二、反序列化
發序列化函數 Unmarshal ,函數簽名:
func Unmarshal(data []byte, v interface{}) error
此時,我們需要創建一個可序列化的byte切片,將其轉換爲struct。
默認的json支持:bool, float64, string,nil
幾種Go類型
反序列化處理未知JSON數據格式
使用interface{}
存儲
舉例:
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
var f interface{}
err := json.Unmarshal(b, &f)
if err != nil {
errors.New("unmarshal error")
}
fmt.Printf("%T, %v\n", f, f)
輸出:
類型: map[string]interface {}
內容: map[Age:6 Name:Wednesday Parents:[Gomez Morticia]]
可以發現,此時key
是string
類型,value是存儲在interface {}
中的,我們可以通過type assertion
獲取:
m := f.(map[string]interface{})
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case float64:
fmt.Println(k, "is float64", vv)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
}
反序列化處理slice、map、pointer
舉例:
type FamilyMember struct {
Name string
Age int
Parents []string
}
func main() {
b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
var n FamilyMember
json.Unmarshal(b, &n)
fmt.Printf("%T, %v\n", n, n)
}
struct中存在一個slice
類型,默認值爲nil。
- 序列化時,若不爲
nil
,則解引用獲得其指向的值,然後序列化 - 反序列化時首先對其初始化爲
nil
,之後再賦值
三、其他序列化函數
函數:
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w, escapeHTML: true}
}
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
func (enc *Encoder) Encode(v interface{}) error {
// ...
}
舉例:
除了 marshal 和 unmarshal 函數,Go 還提供了 Decoder 和 Encoder 對 stream JSON 進行處理。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
var err error
person1 := Person{"張三", 30}
// 編碼結果暫存到 buffer
bytes1 := new(bytes.Buffer)
_ = json.NewEncoder(bytes1).Encode(person1)
if err == nil {
fmt.Print("json.NewEncoder 編碼結果: ", string(bytes1.Bytes()))
}
// 解碼
str2 := bytes1.String()
var person2 Person
// 創建一個 string reader 作爲參數
err = json.NewDecoder(strings.NewReader(str2)).Decode(&person2)
if err == nil {
fmt.Println("json.NewDecoder 解碼結果: ", person2.Name, person2.Age)
}
}
四、nest struct序列化
type App struct {
Id string `json:"id"`
}
type Org struct {
Name string `json:"name"`
}
type AppWithOrg struct {
App
Org
}
func main() {
data := []byte(`
{
"id": "k34rAT4",
"name": "My Awesome Org"
}
`)
var b AppWithOrg
json.Unmarshal(data, &b)
fmt.Printf("%#v", b)
a := AppWithOrg{
App: App{
Id: "k34rAT4",
},
Org: Org{
Name: "My Awesome Org",
},
}
data, _ = json.Marshal(a)
fmt.Println(string(data))
}
vscode 工具相關
1. 刪除當前行ctrl + shift +k
2. vscode插件 String Manipulation 字符串轉換處理(駝峯、大寫開頭、下劃線等等)
使用時ctrl+shift+p 輸入camel即可
3. ctrl+f5直接編譯簡單go文件
參考:http://lwenl.cn/?id=10
https://juejin.im/post/5d5cbc20f265da03ab425227