Golang — json Unmarshal 轉換碰上type interface {} does not support indexing
最近在無聊, 在寫line chat bot, 在接收來自line的event, line會用HTTP POST送到你預先設定的web server, 送的格式為json
在學生時候我很喜歡golang 這語言, 但由於在工作的時候都是使用python, 或是C++(幾乎都是為了效能), 用過python寫web的都知道, 幾乎是最輕鬆的語言沒有之一, 但是在效能上還是有考慮的部分, 在這邊我們就不深入探討, 而這次我在寫web server時使用的是golang的 gin 這個framework, 一個輕便且高效的framwork, 但是在撰寫的部分有時候真的也不像python 那麼得輕鬆, 而我在這邊就遇到一個讀去json的問題
我們都知道python 能輕鬆的將json 轉換成dict的方式, 讓你輕鬆做存取, 但golang在轉換的過程可就沒有這麼順利了, golang轉換json大致上分成兩種
一種是你了解傳送過來json的結構, 利用type struct 去定義好之後再進行讀取
故另一種方式就是利用 map[string]interface{}, 將json 利用json.Unmarshal
ex:
package mainimport (
"encoding/json"
"fmt"
)func main() {
var result map[string]interface{}
json_body := []byte(`{"a":92, "b":[{"c": 123, "d": 1235}]}`)
json.Unmarshal(json_body, &result)
fmt.Println(result)
}
這邊印出的結果會是
map[a:92 b:[map[c:123 d:1235]]]
假設我想要取得b的值map[c:123 d:1235]]
我可以利用 result[“b”]來幫助我完成
package mainimport (
"encoding/json"
"fmt"
)func main() {
var result map[string]interface{}
json_body := []byte(`{"a":92, "b":[{"c": 123, "d": 1235}]}`)
json.Unmarshal(json_body, &result)
fmt.Println(result)
fmt.Println("============")
fmt.Println(result["b"])
}
結果
map[a:92 b:[map[d:1235 c:123]]]
============
[map[c:123 d:1235]]
然而, 若我想進一步取得b裡頭的c值的時候 我們是否能如法炮製用result[“b”][“c”]呢
直接使用會得到一個訊息
type interface {} does not support indexing
為什麼不能這樣用? b裡面存的明明就是一個list(slice)
這邊比較特別的是因為我們的result 是負責mapping [string -> interface{}], 在這邊b的value 為 interface{}.
然而interface{} 並不屬於slice, 故我們無法直接這樣使用, 那我們該如何取得呢
我們可以使用reflect這個函式庫, 它幫助我們可以取得這個interface裡的直並幫助轉換, 將剛剛的程式碼改成以下
package mainimport (
"encoding/json"
"fmt"
"reflect"
)func main() {
var result map[string]interface{}
json_body := []byte(`{"a":92, "b":[{"c": 123, "d": 1235}]}`)
json.Unmarshal(json_body, &result)
fmt.Println(result)
fmt.Println("============")
fmt.Println("b", result["b"])
fmt.Println("============")
value := reflect.ValueOf(result["b"])
c := value.Index(0).Interface().(map[string]interface{})
fmt.Println("c", c)
}
這樣便可以順利的去將c轉換成interface{}, 並且輸出, 當然這樣的方式有點土法煉鋼, 我們也不大可能一直這樣try下去, 故還是得事先了解json的結構利用type struct下去寫會比較合理些
歡迎糾正或討論