Golang語言之JSON解碼函數Unmarshal
- 2019 年 11 月 26 日
- 筆記
前言
工作中我們經常會遇到解碼JSON格式的數據,本文通過4個示例介紹工作中常用到的四種 JSON格式。在 Golang語言中,通常是使用標準庫的encoding/json包中的函數Unmarshal解碼JSON格式的數據,下面我們先介紹一下該函數如何使用,再通過4個示例程式碼來演示一下如何在Golang中解碼常見的4種JSON格式的數據。
func Unmarshal
func Unmarshal(data []byte, v interface{}) error
Unmarshal函數解析json編碼的數據並將結果存入v指向的值。
Unmarshal和Marshal做相反的操作,必要時申請映射、切片或指針,有如下的附加規則:
要將json數據解碼寫入一個指針,Unmarshal函數首先處理json數據是json字面值null的情況。此時,函數將指針設為nil;否則,函數將json數據解碼寫入指針指向的值;如果指針本身是nil,函數會先申請一個值並使指針指向它。
要將json數據解碼寫入一個結構體,函數會匹配輸入對象的鍵和Marshal使用的鍵(結構體欄位名或者它的標籤指定的鍵名),優先選擇精確的匹配,但也接受大小寫不敏感的匹配。
要將json數據解碼寫入一個介面類型值,函數會將數據解碼為如下類型寫入介面:
bool, for JSON booleans float64, for JSON numbers string, for JSON strings []interface{}, for JSON arrays map[string]interface{}, for JSON objects nil for JSON null
如果一個JSON值不匹配給出的目標類型,或者如果一個json數字寫入目標類型時溢出,Unmarshal函數會跳過該欄位並盡量完成其餘的解碼操作。如果沒有出現更加嚴重的錯誤,本函數會返回一個描述第一個此類錯誤的詳細資訊的UnmarshalTypeError。
JSON的null值解碼為go的介面、指針、切片時會將它們設為nil,因為null在json里一般表示「不存在」。 解碼json的null值到其他go類型時,不會造成任何改變,也不會產生錯誤。
當解碼字元串時,不合法的utf-8或utf-16代理(字元)對不視為錯誤,而是將非法字元替換為unicode字元U+FFFD。
普通JSON
示例程式碼:
package main import ( "encoding/json" "fmt" ) // Actress 女演員 type Actress struct { Name string Birthday string BirthPlace string Opus []string } func main() { // 普通JSON // 因為json.UnMarshal() 函數接收的參數是位元組切片, // 所以需要把JSON字元串轉換成位元組切片。 jsonData := []byte(`{ "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":[ "《阿娜爾罕》", "《逆光之戀》", "《克拉戀人》" ] }`) var actress Actress err := json.Unmarshal(jsonData, &actress) if err != nil { fmt.Println("error:", err) return } fmt.Printf("姓名:%sn", actress.Name) fmt.Printf("生日:%sn", actress.Birthday) fmt.Printf("出生地:%sn", actress.BirthPlace) fmt.Println("作品:") for _, val := range actress.Opus { fmt.Println("t", val) } }
運行結果:
姓名:迪麗熱巴
生日:1992-06-03
出生地:新疆烏魯木齊市
作品:
《阿娜爾罕》
《逆光之戀》
《克拉戀人》
JSON內嵌普通JSON
示例程式碼:
package main import ( "encoding/json" "fmt" ) // Opus 作品 type Opus struct { Date string Title string } // Actress 女演員 type Actress struct { Name string Birthday string BirthPlace string Opus Opus } func main () { // JSON嵌套普通JSON jsonData := []byte(`{ "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus": { "Date":"2013", "Title":"《阿娜爾罕》" } }`) var actress Actress err := json.Unmarshal(jsonData, &actress) if err != nil { fmt.Println("error:", err) return } fmt.Printf("姓名:%sn", actress.Name) fmt.Printf("生日:%sn", actress.Birthday) fmt.Printf("出生地:%sn", actress.BirthPlace) fmt.Println("作品:") fmt.Printf("t%s:%s", actress.Opus.Date, actress.Opus.Title)}
運行結果:
姓名:迪麗熱巴
生日:1992-06-03
出生地:新疆烏魯木齊市
作品:
2013:《阿娜爾罕》
JSON內嵌數組JSON
示例程式碼:
package main import ( "encoding/json" "fmt" ) type Opus struct { Date string Title string } type Actress struct { Name string Birthday string BirthPlace string Opus []Opus } func main () { // JSON嵌套數組JSON jsonData := []byte(`{ "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":[ { "date":"2013", "title":"《阿娜爾罕》" }, { "date":"2014", "title":"《逆光之戀》" }, { "date":"2015", "title":"《克拉戀人》" } ] }`) var actress Actress err := json.Unmarshal(jsonData, &actress) if err != nil { fmt.Println("error:", err) return } fmt.Printf("姓名:%sn", actress.Name) fmt.Printf("生日:%sn", actress.Birthday) fmt.Printf("出生地:%sn", actress.BirthPlace) fmt.Println("作品:") for _, val := range actress.Opus { fmt.Printf("t%s - %sn", val.Date, val.Title) } }
運行結果:
姓名:迪麗熱巴
生日:1992-06-03
出生地:新疆烏魯木齊市
作品:
2013 – 《阿娜爾罕》
2014 – 《逆光之戀》
2015 – 《克拉戀人》
JSON內嵌具有動態Key的JSON
示例程式碼:
package main import ( "encoding/json" "fmt" ) // Opus 作品 type Opus struct { Type string Title string } // Actress 女演員 type Actress struct { Name string Birthday string BirthPlace string Opus map[string]Opus } func main () { jsonData := []byte(`{ "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":{ "2013":{ "Type":"近代革命劇", "Title":"《阿娜爾罕》" }, "2014":{ "Type":"奇幻劇", "Title":"《逆光之戀》" }, "2015":{ "Type":"愛情劇", "Title":"《克拉戀人》" } } }`) var actress Actress err := json.Unmarshal(jsonData, &actress) if err != nil { fmt.Println("error:", err) return } fmt.Printf("姓名:%sn", actress.Name) fmt.Printf("生日:%sn", actress.Birthday) fmt.Printf("出生地:%sn", actress.BirthPlace) fmt.Println("作品:") for index, value := range actress.Opus { fmt.Printf("t日期:%sn", index) fmt.Printf("tt分類:%sn", value.Type) fmt.Printf("tt標題:%sn", value.Title) } }
運行結果:
姓名:迪麗熱巴
生日:1992-06-03
出生地:新疆烏魯木齊市
作品:
日期:2013
分類:近代革命劇
標題:《阿娜爾罕》
日期:2014
分類:奇幻劇
標題:《逆光之戀》
日期:2015
分類:愛情劇
標題:《克拉戀人》
總結
我們先是介紹了Golang標準庫的encoding/json包中的Unmarshal函數,然後通過上面4個示例程式碼,分別介紹了如何解碼以下4種JSON格式數據:
JSON格式1: { "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":[ "《阿娜爾罕》", "《逆光之戀》", "《克拉戀人》" ] } JSON格式2: { "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":{ "Date":"2013", "Title":"《阿娜爾罕》" } } JSON格式3: { "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":[ { "date":"2013", "title":"《阿娜爾罕》" }, { "date":"2014", "title":"《逆光之戀》" }, { "date":"2015", "title":"《克拉戀人》" } ] } JSON格式4: { "name":"迪麗熱巴", "birthday":"1992-06-03", "birthPlace":"新疆烏魯木齊市", "opus":{ "2013":{ "Type":"近代革命劇", "Title":"《阿娜爾罕》" }, "2014":{ "Type":"奇幻劇", "Title":"《逆光之戀》" }, "2015":{ "Type":"愛情劇", "Title":"《克拉戀人》" } } }