Golang中为什么无法从GitHub获取JSON响应?

Golang中为什么无法从GitHub获取JSON响应? 以下是我的代码:

func AuthGitHub() error {
	postBody, _ := json.Marshal(map[string]string{
		"client_id": "XXXX",
		"scope": "repo gist user",
	})
	responseBody := bytes.NewBuffer(postBody)

	req, err := http.NewRequest("POST", "https://github.com/login/device/code", responseBody)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("User-Agent", "Blah/0.1")
	if err != nil {
		return err
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	fmt.Println(body)
	sb := string(body)
	fmt.Println(sb)
	return nil
}

文档中提到应该返回JSON格式的响应。

我得到的响应是:

device_code=XXXXX&expires_in=899&interval=5&user_code=XXXX-XXXX&verification_uri=https%3A%2F%2Fgithub.com%2Flogin%2Fdevice

我期望的响应是:

{
  "device_code": "XXXXXX",
  "user_code": "XXXX-XXXX",
  "verification_uri": "https://github.com/login/device",
  "expires_in": 900,
  "interval": 5
}

我是不是漏掉了什么?


更多关于Golang中为什么无法从GitHub获取JSON响应?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

您可能需要在请求中设置 Accept 标头。

更多关于Golang中为什么无法从GitHub获取JSON响应?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用此配置时,我收到一个 {"error":"Not Found"} 响应。

req.Header.Set("Content-Type", "application/json")

应该是

req.Header.Set("Accept", "application/json")

不要在请求体中使用JSON,而是使用URL编码。

编辑:哎呀,我漏掉了一点。如果你得到的响应是URL编码的,你能不能自己解码并将其转换为JSON?

在尝试用Go程序实现之前,你可以使用像Postman或Insomnia Rest Client这样的程序来测试协议。这些工具允许你在表单中输入参数并查看响应。

Content-Type 用于指定你发送的内容类型,Accept 则用于指定你期望接收的内容类型。

你可能需要同时设置两者。

只需稍作实验并查阅文档,你就能明白这一点。

问题在于GitHub API返回的是application/x-www-form-urlencoded格式,而不是application/json格式。你需要使用net/url包来解析响应。

以下是修正后的代码:

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
)

func AuthGitHub() error {
    postBody, _ := json.Marshal(map[string]string{
        "client_id": "XXXX",
        "scope":     "repo gist user",
    })
    responseBody := bytes.NewBuffer(postBody)

    req, err := http.NewRequest("POST", "https://github.com/login/device/code", responseBody)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("User-Agent", "Blah/0.1")
    if err != nil {
        return err
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return err
    }

    // 解析URL编码的响应
    values, err := url.ParseQuery(string(body))
    if err != nil {
        return err
    }

    // 转换为JSON格式
    result := map[string]interface{}{
        "device_code":      values.Get("device_code"),
        "user_code":        values.Get("user_code"),
        "verification_uri": values.Get("verification_uri"),
        "expires_in":       values.Get("expires_in"),
        "interval":         values.Get("interval"),
    }

    jsonResult, _ := json.MarshalIndent(result, "", "  ")
    fmt.Println(string(jsonResult))

    return nil
}

或者,如果你需要直接使用解析后的值:

func AuthGitHub() (map[string]string, error) {
    // ... 前面的代码相同 ...

    values, err := url.ParseQuery(string(body))
    if err != nil {
        return nil, err
    }

    result := map[string]string{
        "device_code":      values.Get("device_code"),
        "user_code":        values.Get("user_code"),
        "verification_uri": values.Get("verification_uri"),
        "expires_in":       values.Get("expires_in"),
        "interval":         values.Get("interval"),
    }

    return result, nil
}

GitHub OAuth设备流程的响应确实是URL编码格式,这是API设计的特性。使用url.ParseQuery可以正确解析这种格式的响应数据。

回到顶部