web-dev-qa-db-fra.com

Comment envoyer une chaîne JSON dans un POST demande en Go

J'ai essayé de travailler avec Apiary et j'ai créé un modèle universel pour envoyer JSON afin de simuler le serveur et obtenir le code suivant:

package main

import (
    "encoding/json"
    "fmt"
    "github.com/jmcvetta/napping"
    "log"
    "net/http"
)

func main() {
    url := "http://restapi3.apiary.io/notes"
    fmt.Println("URL:>", url)

    s := napping.Session{}
    h := &http.Header{}
    h.Set("X-Custom-Header", "myvalue")
    s.Header = h

    var jsonStr = []byte(`
{
    "title": "Buy cheese and bread for breakfast."
}`)

    var data map[string]json.RawMessage
    err := json.Unmarshal(jsonStr, &data)
    if err != nil {
        fmt.Println(err)
    }

    resp, err := s.Post(url, &data, nil, nil)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("response Status:", resp.Status())
    fmt.Println("response Headers:", resp.HttpResponse().Header)
    fmt.Println("response Body:", resp.RawText())

}

Ce code n'envoie pas JSON correctement, mais je ne sais pas pourquoi. La chaîne JSON peut être différente à chaque appel. Je ne peux pas utiliser Struct pour cela.

164
Ladislav Prskavec

Je ne connais pas bien la sieste, mais utiliser le paquetage net/http de Golang fonctionne bien ( playground ): 

func main() {
    url := "http://restapi3.apiary.io/notes"
    fmt.Println("URL:>", url)

    var jsonStr = []byte(`{"title":"Buy cheese and bread for breakfast."}`)
    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
    req.Header.Set("X-Custom-Header", "myvalue")
    req.Header.Set("Content-Type", "application/json")

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

    fmt.Println("response Status:", resp.Status)
    fmt.Println("response Headers:", resp.Header)
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println("response Body:", string(body))
}
371
OneOfOne

vous pouvez simplement utiliser post pour publier votre json. 

values := map[string]string{"username": username, "password": password}

jsonValue, _ := json.Marshal(values)

resp, err := http.Post(authAuthenticatorUrl, "application/json", bytes.NewBuffer(jsonValue))
62
gaozhidf

En plus du paquetage net/http standard, vous pouvez envisager d’utiliser my GoRequest qui encapsule net/http et vous simplifie la vie sans trop penser à json ou struct. Mais vous pouvez également mélanger et assortir les deux en une seule demande! (vous pouvez voir plus de détails à ce sujet sur la page goreub de github) 

Donc, à la fin, votre code deviendra comme suit:

func main() {
    url := "http://restapi3.apiary.io/notes"
    fmt.Println("URL:>", url)
    request := gorequest.New()
    titleList := []string{"title1", "title2", "title3"}
    for _, title := range titleList {
        resp, body, errs := request.Post(url).
            Set("X-Custom-Header", "myvalue").
            Send(`{"title":"` + title + `"}`).
            End()
        if errs != nil {
            fmt.Println(errs)
            os.Exit(1)
        }
        fmt.Println("response Status:", resp.Status)
        fmt.Println("response Headers:", resp.Header)
        fmt.Println("response Body:", body)
    }
}

Cela dépend de la façon dont vous voulez atteindre. J'ai créé cette bibliothèque parce que j'ai le même problème avec vous et que je veux un code plus court, facile à utiliser avec json et plus facile à gérer dans ma base de code et mon système de production.

11
A-letubby

Si vous avez déjà un struct.

type Student struct {
    Name    string `json:"name"`
    Address string `json:"address"`
}

// .....

body := &Student{
    Name:    "abc",
    Address: "xyz",
}

buf := new(bytes.Buffer)
json.NewEncoder(buf).Encode(body)
req, _ := http.NewRequest("POST", url, buf)

res, e := client.Do(req)
if e != nil {
    return e
}

defer res.Body.Close()
io.Copy(os.Stdout, res.Body)
0
Ninh Pham