我对Go来说还比较陌生,尽管到目前为止我对大部分内容都掌握得很好,但是我仍然无法确切地知道应该如何处理JSON。
因此,假设我在前端有一个访问令牌。我想通过它,并向API提出请求以对其进行验证。
这是传递给后端的json:
{
"accessToken": "xxxxxx"
}
type test_struct struct {
AccessToken string `json:"accessToken"`
}
func validateFacebookLogin(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var t test_struct
err := decoder.Decode(&t)
if err != nil {
panic(err)
}
tokenCheck := "xxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx"
req, err := http.NewRequest("GET", "https://graph.facebook.com/debug_token", nil)
if err != nil {
log.Print(err)
os.Exit(1)
}
q := req.URL.Query()
q.Add("input_token", t.AccessToken)
q.Add("access_token", tokenCheck)
req.URL.RawQuery = q.Encode()
resp, err := http.Get(req.URL.String())
defer resp.Body.Close()
bodyBytes, _ := ioutil.ReadAll(resp.Body)
bodyString := string(bodyBytes)
fmt.Println(bodyString);
json.NewEncoder(w).Encode(map[string]string{"message": "FINE"})
json.NewEncoder(w).Encode(resp)
}
我能找到的所有文档似乎都表明应该为所有JSON响应/请求创建一个结构(除非我误会了)。这样不方便吗?如果我的嵌套JSON响应异常大怎么办?我必须创建COMPLETE响应的结构吗?
我在ioutil上使用的方法是不好的做法吗?在哪里我可以传回整个字符串表示形式并设法在前端对其进行解码?
我想我的主要问题是,何时应将JSON分配给结构?什么是最佳做法?如果我打算立即将响应返回到前端,那有什么意义吗?
假设我确实想在后端维护数据,那么是否有任何“更好”的方法来处理较大的响应?
答案 0 :(得分:2)
在大多数情况下,您只需要简单地利用json.Unmarshal。该用例在大多数情况下都有效:
var myClient = &http.Client{Timeout: 10 * time.Second}
func getJson(url string, target interface{}) error {
r, err := myClient.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
foo := Foo{}
getJson("http://example.com", &foo2)
fmt.Printf("%+v\n", foo)
但是,如果您真正使用的是大型数据集,请查看https://golang.org/pkg/encoding/json/#example_Decoder_Decode_stream
package main
import (
"encoding/json"
"fmt"
"log"
"strings"
)
func main() {
const jsonStream = `
[
{"Name": "Ed", "Text": "Knock knock."},
{"Name": "Sam", "Text": "Who's there?"},
{"Name": "Ed", "Text": "Go fmt."},
{"Name": "Sam", "Text": "Go fmt who?"},
{"Name": "Ed", "Text": "Go fmt yourself!"}
]
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
// read open bracket
t, err := dec.Token()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)
// while the array contains values
for dec.More() {
var m Message
// decode an array value (Message)
err := dec.Decode(&m)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v: %v\n", m.Name, m.Text)
}
// read closing bracket
t, err = dec.Token()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)
}
这将使您以更高效的内存工作方式。
更多关于您的问题:
如果我没有回答,请告诉我。
编辑:对于ioutil.ReadAll
的用法-一般来说,您需要解组为一个结构,以便实际上可以使用数据,并且通过您的结构从类型安全中受益。如果您只需要字符串,那么您在做什么就可以了,但是通常不是这种情况。