1. 程式人生 > >Go基礎程式設計:JSON處理

Go基礎程式設計:JSON處理

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不會匯出到JSONCompany 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")
        }
    }
}

執行結果:
這裡寫圖片描述

3 參考資料