为了账号安全,请及时绑定邮箱和手机立即绑定

Go 处理 JSON 响应和请求

Go 处理 JSON 响应和请求

Go
胡说叔叔 2023-06-01 15:02:26
我是 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 响应怎么办?我必须创建完整响应的结构吗?我在上面使用的方法是 ioutil 不好的做法吗?我在哪里可以传回整个字符串表示并在前端管理解码?我想我的主要问题是,什么时候应该将我的 JSON 分配给结构?什么是最佳实践?如果我只想立即将响应返回给前端,有什么意义吗?假设我确实想在后端维护数据,是否有任何“更好”的方法来处理大型响应?
查看完整描述

1 回答

?
MM们

TA贡献1886条经验 获得超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)


}

这将使您能够以更高效的内存方式工作。

对于您的更多问题:

  1. 我是否必须解组为完整的响应结构?- 不是真的,你只需要定义你想在结构中使用的东西,其余的将被忽略

  2. 你做对了吗?- 你没有做任何本质上错误的事情吗?

如果有什么我没有回答的,请告诉我。

对于您的使用ioutil.ReadAll-一般来说,您需要解组为一个结构,以便您可以实际使用数据,并通过您的结构从类型安全中受益。如果您确实只需要字符串,那么您所做的就很好,但通常情况并非如此。


查看完整回答
反对 回复 2023-06-01
  • 1 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信