Go基礎程式設計:JSON處理
阿新 • • 發佈:2019-02-08
JSON (JavaScript Object Notation)是一種比XML更輕量級的資料交換格式,在易於人們閱讀和編寫的同時,也易於程式解析和生成。儘管JSON是JavaScript的一個子集,但JSON採用完全獨立於程式語言的文字格式,且表現為鍵/值對集合的文字描述形式(類似一些程式語言中的字典結構),這使它成為較為理想的、跨平臺、跨語言的資料交換語言。
開發者可以用 JSON 傳輸簡單的字串、數字、布林值,也可以傳輸一個數組,或者一個更復雜的複合結構。在 Web 開發領域中, JSON被廣泛應用於 Web 服務端程式和客戶端之間的資料通訊。
Go語言內建對JSON的支援。使用Go語言內建的encoding/json 標準庫,開發者可以輕鬆使用Go程式生成和解析JSON格式的資料。
1 編碼JSON
1.1 通過結構體生成JSON
使用json.Marshal()函式可以對一組資料進行JSON格式的編碼。 json.Marshal()函式的宣告如下:
func Marshal(v interface{}) ([]byte, error)
還有一個格式化輸出:
// MarshalIndent 很像 Marshal,只是用縮排對輸出進行格式化
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
1) 編碼JSON
示例程式碼:
package main
import (
"encoding/json"
"fmt"
)
type IT struct {
Company string
Subjects []string
IsOk bool
Price float64
}
func main() {
t1 := IT{"itcast", []string{"Go", "C++", "Python", "Test"}, true, 666.666}
//生成一段JSON格式的文字
//如果編碼成功, err 將賦於零值 nil,變數b 將會是一個進行JSON格式化之後的[]byte型別
//b, err := json.Marshal(t1)
//輸出結果:{"Company" :"itcast","Subjects":["Go","C++","Python","Test"],"IsOk":true,"Price":666.666}
b, err := json.MarshalIndent(t1, "", " ")
/*
輸出結果:
{
"Company": "itcast",
"Subjects": [
"Go",
"C++",
"Python",
"Test"
],
"IsOk": true,
"Price": 666.666
}
*/
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(string(b))
}
2) struct tag
我們看到上面的輸出欄位名的首字母都是大寫的,如果你想用小寫的首字母怎麼辦呢?把結構體的欄位名改成首字母小寫的?JSON輸出的時候必須注意,只有匯出的欄位(首字母是大寫)才會被輸出,如果修改欄位名,那麼就會發現什麼都不會輸出,所以必須通過struct tag定義來實現。
針對JSON的輸出,我們在定義struct tag的時候需要注意的幾點是:
- 欄位的tag是”-“,那麼這個欄位不會輸出到JSON
- tag中帶有自定義名稱,那麼這個自定義名稱會出現在JSON的欄位名中
- tag中如果帶有”omitempty”選項,那麼如果該欄位值為空,就不會輸出到JSON串中
- 如果欄位型別是bool, string, int, int64等,而tag中帶有”,string”選項,那麼這個欄位在輸出到JSON的時候會把該欄位對應的值轉換成JSON字串
示例程式碼:
type IT struct {
//Company不會匯出到JSON中
Company string `json:"-"`
// Subjects 的值會進行二次JSON編碼
Subjects []string `json:"subjects"`
//轉換為字串,再輸出
IsOk bool `json:",string"`
// 如果 Price 為空,則不輸出到JSON串中
Price float64 `json:"price, omitempty"`
}
func main() {
t1 := IT{Company: "itcast", Subjects: []string{"Go", "C++", "Python", "Test"}, IsOk: true}
b, err := json.Marshal(t1)
//json.MarshalIndent(t1, "", " ")
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(string(b))
//輸出結果:{"subjects":["Go","C++","Python","Test"],"IsOk":"true","price":0}
}
1.2 通過map生成JSON
// 建立一個儲存鍵值對的對映
t1 := make(map[string]interface{})
t1["company"] = "itcast"
t1["subjects "] = []string{"Go", "C++", "Python", "Test"}
t1["isok"] = true
t1["price"] = 666.666
b, err := json.Marshal(t1)
//json.MarshalIndent(t1, "", " ")
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(string(b))
//輸出結果:{"company":"itcast","isok":true,"price":666.666,"subjects ":["Go","C++","Python","Test"]}
2 解碼JSON
可以使用json.Unmarshal()函式將JSON格式的文字解碼為Go裡面預期的資料結構。
json.Unmarshal()函式的原型如下:
func Unmarshal(data []byte, v interface{}) error
該函式的第一個引數是輸入,即JSON格式的文字(位元序列),第二個引數表示目標輸出容器,用於存放解碼後的值。
2.1 解析到結構體
type IT struct {
Company string `json:"company"`
Subjects []string `json:"subjects"`
IsOk bool `json:"isok"`
Price float64 `json:"price"`
}
func main() {
b := []byte(`{
"company": "itcast",
"subjects": [
"Go",
"C++",
"Python",
"Test"
],
"isok": true,
"price": 666.666
}`)
var t IT
err := json.Unmarshal(b, &t)
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(t)
//執行結果:{itcast [Go C++ Python Test] true 666.666}
//只想要Subjects欄位
type IT2 struct {
Subjects []string `json:"subjects"`
}
var t2 IT2
err = json.Unmarshal(b, &t2)
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(t2)
//執行結果:{[Go C++ Python Test]}
}
2.2 解析到interface
示例程式碼:
func main() {
b := []byte(`{
"company": "itcast",
"subjects": [
"Go",
"C++",
"Python",
"Test"
],
"isok": true,
"price": 666.666
}`)
var t interface{}
err := json.Unmarshal(b, &t)
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(t)
//使用斷言判斷型別
m := t.(map[string]interface{})
for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case int:
fmt.Println(k, "is int", vv)
case float64:
fmt.Println(k, "is float64", vv)
case bool:
fmt.Println(k, "is bool", 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")
}
}
}
執行結果: