英文:
Parsing a JSON response using Unmarshal
问题
我正在尝试使用以下代码解析JSON响应:
type Token struct {
Access_token string `json:"access_token"`
Token_type string `json:"token_type"`
Expires_in int `json:"expires_in"`
}
homeURL := "https:/blah.com/oauth2/token"
v := url.Values{}
v.Set("client_id", "xxx")
v.Set("client_secret", "xxx")
v.Set("grant_type", "xxx")
s := v.Encode()
req, err := http.NewRequest("POST", homeURL, strings.NewReader(s))
if err != nil {
fmt.Printf("http.NewRequest() error: %v\n", err)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
var client = http.Client{}
resp, err := client.Do(req)
if err != nil {
//error
fmt.Printf("http.Do() error: %v\n", err)
return
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
var token Token
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error parsing JSON\n")
}
errj := json.Unmarshal(data, &token)
if errj != nil {
fmt.Println("JSON PARSING ERROR")
}
fmt.Printf("read resp.Body successfully:\n%v\n", string(data))
fmt.Printf("Response Headers \n%v\n", resp.Header)
fmt.Println(token.Access_token)
} else {
fmt.Println("Request failed !", resp.StatusCode)
}
我还尝试使用以下代码:
json.NewDecoder(resp.Body).Decode(&token)
然而,我无法填充token结构,并且没有错误。我收到的响应看起来很正常:
read resp.Body successfully:
`{"access_token":"Osq","token_type":"Bearer","expires_in":"1247"}
Response Headers
map[Content-Length:[384] Connection:[keep-alive] Content-Language:[en-US] Date:[Tue, 08 Aug 2017 16:52:19 GMT] Gi-Coordination-Id:[auto_--YfYqIVya0KiAv_mLLET8g] Server:[Mashery Proxy] X-Powered-By:[ASP.NET ARR/3.0 ASP.NET] Content-Type:[application/json; charset=utf-8] Pragma:[no-cache] Cache-Control:[no-cache,no-cache] Expires:[-1]]`
有人对我使用的方法有什么错误的想法吗?
编辑 - 解决方案:
type Token struct {
Access_token string `json:"access_token"`
Token_type string `json:"token_type"`
Expires_in int `json:"expires_in"`
}
// Unmarshal需要首字母大写的导出键。
请注意,我只翻译了代码部分,其他内容不予翻译。
英文:
I am trying to parse a JSON response with the following code:
type Token struct {
access_token string `json:access_token`
token_type string `json:token_type`
expires_in int `json:expires_in`
}
homeURL := "https:/blah.com/oauth2/token"
v := url.Values{}
v.Set("client_id", "xxx")
v.Set("client_secret", "xxx")
v.Set("grant_type", "xxx")
s := v.Encode()
req, err := http.NewRequest("POST", homeURL, strings.NewReader(s))
if err != nil {
fmt.Printf("http.NewRequest() error: %v\n", err)
return
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
var client = http.Client{}
resp, err := client.Do(req)
if err != nil {
//error
fmt.Printf("http.Do() error: %v\n", err)
return
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
var token Token
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error parsing JSON\n")
}
errj := json.Unmarshal(data, &token)
if errj != nil {
fmt.Println("JSON PARSING ERROR")
}
fmt.Printf("read resp.Body successfully:\n%v\n", string(data))
fmt.Printf("Response Headers \n%v\n", resp.Header)
fmt.Println(token.access_token)
} else {
fmt.Println("Request failed !" , resp.StatusCode)
}
I also tried to use
json.NewDecoder(resp.Body).Decode(&token)
However I am unable to get the token structure populated and there are no errors. The response I am getting back looks fine
read resp.Body successfully:
{"access_token":"Osq","token_type":"Bearer","expires_in":"1247"}
Response Headers
map[Content-Length:[384] Connection:[keep-alive] Content-Language:[en-US] Date:[Tue, 08 Aug 2017 16:52:19 GMT] Gi-Coordination-Id:[auto_--YfYqIVya0KiAv_mLLET8g] Server:[Mashery Proxy] X-Powered-By:[ASP.NET ARR/3.0 ASP.NET] Content-Type:[application/json; charset=utf-8] Pragma:[no-cache] Cache-Control:[no-cache,no-cache] Expires:[-1]]
Does anyone have any ideas on what I am doing wrong with either approach ?
EDIT - Solution:
type Token struct {
Access_token string `json:access_token`
Token_type string `json:token_type`
Expires_in int `json:expires_in`
}
Unmarshal needs the exported keys which need to be capitalised.
答案1
得分: 4
在Token
中,你有未导出的字段(以小写字母开头的字段)。因为这些字段没有被导出,json
无法看到它们,因此无法将其解组。请阅读json.Unmarshal的文档:
> 为了将JSON解组到结构体中,Unmarshal会将传入的对象键与Marshal使用的键进行匹配(可以是结构体字段名或其标签),优先选择精确匹配,但也接受不区分大小写的匹配。Unmarshal只会设置结构体的导出字段。
英文:
You have unexported fields in Token
(fields starting with a lower-case letter). Because the fields are not exported, json
cannot see them, and so cannot unmarshal into them. Please read the documentation for json.Unmarshal
:
> To unmarshal JSON into a struct, Unmarshal matches incoming object
> keys to the keys used by Marshal (either the struct field name or its
> tag), preferring an exact match but also accepting a case-insensitive
> match. Unmarshal will only set exported fields of the struct.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论