我已將 Github 和 Google 身份驗證系統添加到我的 Web 應用程式中。在這兩種情況下,我都希望獲得用戶電子郵件。我嘗試制作一個可以發出 API 請求并獲取電子郵件的函式。當Google 回傳一個 JSON 物件并在 Github 上回傳一個 JSON 陣列作為回應
時,我遇到了一個問題。
我無法弄清楚如何避免兩次呼叫 JSON 解碼器,因為我不能為它們兩個使用相同的型別變數。
// Sends a request to the API and
// authorizes it by setting HTTP header "Authorization" to authHeader value
func getUserEmail(endpoint, authHeader, provider string) (string, error) {
var email string // Store user email here
var client http.Client // Create client so we can modify request headers
// Create a GET request to the endpoint
req, err := http.NewRequest("GET", endpoint, nil)
if err != nil {
return "", err
}
// Authorize the request by using the HTTP header
req.Header.Add("Authorization", authHeader)
// Give the data back as JSON
req.Header.Add("accept", "application/json")
// Send the request
resp, err := client.Do(req)
if err != nil {
fmt.Println("Internet connection or client policy error")
return "", err
}
defer resp.Body.Close()
if provider == "google" {
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
fmt.Println("Error occured during decoding access token response")
return "", err
}
email = response["email"].(string)
} else if provider == "github" {
var response []map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
fmt.Println("Error occured during decoding access token response")
return "", err
}
email = response[0]["email"].(string)
} else {
return "", errors.New("invalid provider")
}
return email, nil
}
uj5u.com熱心網友回復:
您可以解組為var response interface{}. 一旦 json 被解組,你可以在type assertion上做一個response檢查它是否是[]interface{}或map[string]interface{}從那里去。
var email string
var response interface{}
if err := json.NewDecoder(r.Body).Decode(&response); err != nil {
return err
}
// If you are sure that the structure of the content of the response,
// given its type, is always what you expect it to be, you can use a
// quick-and-dirty type switch/assertion.
switch v := response.(type) {
case []interface{}:
email = v[0].(map[string]interface{})["email"].(string)
case map[string]interface{}:
email = v["email"].(string)
}
// But! If you're not sure, if the APIs don't provide a guarantee,
// then you should guard against panics using the comma-ok idiom
// at every step.
if s, ok := response.([]interface{}); ok && len(s) > 0 {
if m, ok := s[0].(map[string]interface{}); ok && len(m) > 0 {
email, _ = m["email"].(string)
}
} else if m, ok := response.(map[string]interface{}); ok && len(m) > 0 {
email, _ = m["email"].(string)
}
您還可以根據提供者值預先分配一個指向預期型別的??指標,并將請求正文解組到其中,這將減少必要的型別斷言的數量,但需要指標解參考。
var email string
var response interface{}
if provider == "google" {
response = new(map[string]interface{})
} else if provider == "github" {
response = new([]map[string]interface{})
}
if err := json.NewDecoder(r.Body).Decode(response); err != nil {
return err
}
switch v := response.(type) {
case *[]map[string]interface{}:
email = (*v)[0]["email"].(string) // no need to assert the slice element's type
case *map[string]interface{}:
email = (*v)["email"].(string)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/422097.html
標籤:
