395 Stimmen

Wie sende ich einen JSON-String in einer POST-Anfrage in Go?

Ich habe versucht, mit Apiary zu arbeiten und eine universelle Vorlage erstellt, um JSON an den Mock-Server zu senden, und habe diesen Code:

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": "Kaufe Käse und Brot zum Frühstück."}`)    
  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())
}

Dieser Code sendet JSON nicht richtig, aber ich weiß nicht warum. Der JSON-String kann bei jedem Aufruf anders sein. Ich kann kein Struct dafür verwenden.

6voto

Verwenden Sie io.Pipe für große Anforderungskörper, wie in einer anderen Antwort erwähnt. Dieser Ansatz vermeidet den Aufbau des gesamten Anforderungskörpers im Speicher, indem die Daten vom JSON-Encoder zum Netzwerk gestreamt werden.

Diese Antwort baut auf der anderen Antwort auf, indem gezeigt wird, wie Fehler behandelt werden. Behandeln Sie immer Fehler!

  • Verwenden Sie die Funktion CloseWithError der Pipe, um Codierfehler an den Fehler zurückzugeben, der von http.Post zurückgegeben wird.
  • Behandeln Sie den Fehler, der von http.Post zurückgegeben wird.
  • Schließen Sie den Antwortkörper.

Hier ist der Code:

r, w := io.Pipe()

go func() {
    w.CloseWithError(json.NewEncoder(w).Encode(data))
}()

// Stellen Sie sicher, dass die Lese-Seite der Pipe geschlossen ist. Dies
// entsperrt die Goroutine in einem Szenario, in dem http.Post
// ausfällt, bevor der gesamte Anforderungskörper gelesen wird.
defer r.Close()

resp, err := http.Post(url, r)
if err != nil {
    // Passen Sie hier die Fehlerbehandlung an, um den Anforderungen der Anwendung gerecht zu werden.
    log.Fatal(err)
}
defer resp.Body.Close()
// Verwenden Sie hier die Antwort.

3voto

Zombo Punkte 1

Wenn Sie viele Daten senden müssen, können Sie eine Pipe verwenden:

package main

import (
   "encoding/json"
   "io"
   "net/http"
)

func main() {
   m := map[string]int{"SNG_ID": 75498415}
   r, w := io.Pipe()
   go func() {
      json.NewEncoder(w).Encode(m)
      w.Close()
   }()
   http.Post("https://stackoverflow.com", "application/json", r)
}

https://golang.org/pkg/io#Pipe

3voto

Isanka Wijerathne Punkte 2687

Ich würde das net/http-Paket anstelle des napping verwenden.

package main

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

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

    client := &http.Client{}

    var jsonStr = []byte(`
{
    "title": "Käse und Brot für das Frühstück kaufen."
}`)

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
    if err != nil {
        log.Fatal(err)
    }

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

    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()

    fmt.Println("Antwort Status:", resp.Status)
    fmt.Println("Antwort Header:", resp.Header)

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Antwort Body:", string(body))
}

Dies erstellt eine neue POST-Anfrage mit den JSON-Daten als Anfragekörper, setzt die erforderlichen Header und sendet die Anfrage mit einem http.Client.

  • Platzhalter* ersetzen.

1voto

Highdeger Punkte 21

Wenn Sie es so machen möchten, müssen Sie diese Karte zur Umwandlung von JSON-Strings verwenden.

var data map[string]interface{}

Aber wenn Sie den JSON jedes Mal ändern müssen und die Initialisierung Ihres Anforderungskörpers bequemer gestalten möchten, können Sie diese Karte zur Erstellung des JSON-Körpers verwenden.

var bodyJsonMap map[string]interface{}{
    "key1": val1,
    "key2": val2,
    ...
}

Dann wandeln Sie es in einen JSON-String um.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X