Идти обрабатывать ответы и запросы JSON - PullRequest
0 голосов
/ 14 января 2019

Я относительно новичок в 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? Должен ли я создать структуру полного ответа?

Является ли метод, который я использую выше, плохой практикой? Где я мог бы просто передать обратно целое строковое представление и управлять его декодированием во внешнем интерфейсе?

Полагаю, мой главный вопрос: когда мне назначить JSON для структуры? Что считается лучшей практикой? Если я намереваюсь просто немедленно вернуть ответ в интерфейс, есть ли смысл в этом?

И, если я хочу сохранить данные на бэкэнде, есть ли "лучший" метод для обработки больших ответов?

1 Ответ

0 голосов
/ 14 января 2019

В большинстве случаев вам нужно просто использовать 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 - Вообще говоря, вы захотите разархивировать структуру, чтобы вы могли использовать данных и пользоваться безопасностью типов через ваши структуры. Если вам буквально нужна строка, то то, что вы делаете, хорошо, но обычно это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...