2014-01-12 63 views
4

我在寫一個JSON列表爲空的測試。如何在界面上調用len()?

{"matches": []} 

對象的類型爲map[string]interface{},我想測試列表是空的。

var matches := response["matches"] 
if len(matches) != 0 { 
    t.Errorf("Non-empty match list!") 
} 

但是我在編譯的時候聽說,這是無效的

invalid argument matches (type interface {}) for len 

如果我嘗試強制轉換爲列表類型:

matches := response["matches"].([]string) 

我得到了恐慌:

panic: interface conversion: interface is []interface {}, not []string [recovered] 

我想在這裏寫什麼?

+0

如果你可以避免它,不要使用'interface {}'。這是沒有必要的音樂的時間。例如,如果這是你想要的,則將其解析爲'map [string] []字符串。或者一個struct – Dustin

回答

11

在Go中使用地圖的JSON解析使用的接口無處不在。想象一下,你有以下JSON對象:

{ 
    "stuff" : [ 
     "stuff1", 
     "stuff2", 
     "stuff3", 
    ] 
} 

轉到JSON庫將解析外部對象從鍵映射到值,你已經在你的代碼所示。它將變量名稱映射爲與這些變量名稱對應的值。但是,由於它無法提前知道這些值,因此地圖的值類型僅爲interface{}。所以我們假設你知道有一個叫做"stuff"的鍵,你知道它的值是一個數組。你可以這樣做:

arr := myMap["stuff"] 

而且你知道,它是一個數組類型,這樣你就可以真正代替做到:

arr := myMap["stuff"].([]interface{}) 

這裏的問題是,當你說得對,這是一個數組, JSON庫知道這一點,它無法知道每個元素將是string類型,所以無法確定數組類型實際上應該是[]string。試想一下,如果你做了這個:

{ 
    "stuff" : [ 
     "stuff1", 
     "stuff2", 
     3 
    ] 
} 

"stuff"現在不能是一個字符串數組,因爲元素之一不是字符串。事實上,它不能是任何東西的數組 - 沒有單一類型可以滿足所有元素的類型。所以這就是爲什麼Go JSON庫別無選擇,只能將其保留爲[]interface{}。幸運的是,因爲你想要的只是長度,你已經完成了。你可以這樣做:

arr := myMap["stuff"].([]interface{}) 
l := len(arr) 

現在,這一切優秀和良好的,但讓我們說下你想真正看到的要素之一的道路。現在,您可以拿出一個元素,並知道它是一個字符串,這樣做:

arr := myMap["stuff"].([]interface{}) 
iv := arr[0] // interface value 
sv := iv.(string) // string value 

注意

當我說「陣列」,我指的是在JSON傳感陣列 - 這是JSON數組。在Go中表示它們的數據結構稱爲「切片」(Go也包含數組,但它們是獨立的 - 如果您習慣於像C或Java這樣的語言的數組,則Go切片是最接近的模擬)。

+0

原諒我挑剔,但'[] interface {}'不是一個數組(在Go術語中),它是一個切片。 – MatrixFrog

+0

我知道 - 我的意思是JSON意義上的數組。 – joshlf

+0

我加了一個簡短的說明,雖然 - 很好的電話。 – joshlf