2013-03-28 14 views
166

私は次のことを信じられないように思えます.Goはこれよりもライブラリのデザインが優れていると思いますが、Goを使ってPOSTを処理する例は見つかりませんJSONデータのリクエストそれらはすべてフォームPOSTです。ログが埋め込まれて、curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/testGoでのJSONのポストリクエストの処理

そしてここでのコードは次のとおりです:ここで

は、例えば、要求され

package main 

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

type test_struct struct { 
    Test string 
} 

func test(rw http.ResponseWriter, req *http.Request) { 
    req.ParseForm() 
    log.Println(req.Form) 
    //LOG: map[{"test": "that"}:[]] 
    var t test_struct 
    for key, _ := range req.Form { 
     log.Println(key) 
     //LOG: {"test": "that"} 
     err := json.Unmarshal([]byte(key), &t) 
     if err != nil { 
      log.Println(err.Error()) 
     } 
    } 
    log.Println(t.Test) 
    //LOG: that 
} 

func main() { 
    http.HandleFunc("/test", test) 
    log.Fatal(http.ListenAndServe(":8082", nil)) 
} 

そこは右、より良い方法があるはずですか?私はベストプラクティスが何であるかを見つけ出すだけで困っている。

(Goはまた、検索エンジンにGolangとして知られており、他の人がそれを見つけることができますので、ここで言及されている。)

+3

あなたが 'curl -X POST -H 'を使うならば、Content-Type:application/json' -d '{\" test \ ":\" that \ "}" '、' req.Form ["test" ] '返すべきである' '' '' '' ' – Vinicius

+0

@Viniciusはこれについて何か証拠がありますか? – diraria

答えて

255

json.Unmarshalの代わりにjson.Decoderを使用してください。

func test(rw http.ResponseWriter, req *http.Request) { 
    decoder := json.NewDecoder(req.Body) 
    var t test_struct 
    err := decoder.Decode(&t) 
    if err != nil { 
     panic(err) 
    } 
    defer req.Body.Close() 
    log.Println(t.Test) 
} 
+39

理由を教えてください。 –

+43

開始すると、バッファにすべてをロードする必要はなく、ストリームを処理できるように見えます。 (私は別のBTWです) – Joe

+4

この場合、どのように適切なエラー処理が行われるのだろうかと思います。私はそれが無効なjsonについてパニックになるのは良い考えだとは思わない。 – codepushr

48

あなたはreq.Bodyから読み取るする必要があります。 ParseFormメソッドはreq.Bodyから読み取り、それを標準のHTTPエンコード形式で解析しています。あなたが望むのは、本文を読み込んでJSON形式で解析することです。

ここにコードが更新されました。

package main 

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

type test_struct struct { 
    Test string 
} 

func test(rw http.ResponseWriter, req *http.Request) { 
    body, err := ioutil.ReadAll(req.Body) 
    if err != nil { 
     panic(err) 
    } 
    log.Println(string(body)) 
    var t test_struct 
    err = json.Unmarshal(body, &t) 
    if err != nil { 
     panic(err) 
    } 
    log.Println(t.Test) 
} 

func main() { 
    http.HandleFunc("/test", test) 
    log.Fatal(http.ListenAndServe(":8082", nil)) 
} 
+0

私はおそらくそれを取得していないでしょうが、 '' 'req * http.Request'''にすでにあるものを私に返すだけでしょうか? – TomJ

+0

実際、私は答えを更新しました。私の最初の答えは間違っていた。私はこれを試しました。 – Daniel

+0

ありがとう!私はどこに間違っていたのか分かります。この問題を解決しようとする初期の試みで '' 'req.ParseForm()' 'を呼び出すと、' 'req.Body'''を試してみる前に、あなたが '' Unmarshal''(少なくとも1.0.2で)に行くと、body outと '' JSON input''の予期しない終了がスローされます。 – TomJ

11

次の例は、docsから得たものです(ソースhere)。

package main 

import (
    "encoding/json" 
    "fmt" 
    "io" 
    "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)) 
    for { 
     var m Message 
     if err := dec.Decode(&m); err == io.EOF { 
      break 
     } else if err != nil { 
      log.Fatal(err) 
     } 
     fmt.Printf("%s: %s\n", m.Name, m.Text) 
    } 
} 

OPは、我々はconst jsonStreamを落とすことになる場合には

type test_struct struct { 
    Test string 
} 

を...デコード、およびtest_structMessage構造体を置き換えるために探していたということで、ここでの鍵:

func test(rw http.ResponseWriter, req *http.Request) { 
    dec := json.NewDecoder(req.Body) 
    for { 
     var t test_struct 
     if err := dec.Decode(&t); err == io.EOF { 
      break 
     } else if err != nil { 
      log.Fatal(err) 
     } 
     log.Printf("%s\n", t.Test) 
    } 
} 

更新:私はまた、this postが応答に関するいくつかの素晴らしいデータを提供すると付け加えますJSONも同様です。私が気づいていなかったstruct tagsについての説明があります。

JSONは通常{"Test": "test", "SomeKey": "SomeVal"}のように見えるのではなく、{"test": "test", "somekey": "some value"}ていないので、あなたはこのようなあなたの構造体を再構築することができます

​​

...とは対照的に、今、あなたのハンドラは、「いくつかのキー」を使用してJSONをパースします「SomeKey」(これは内部的に使用されます)に移動します。

+1

コードがコンパイルされません。あなたがテストに与えられたものreq.Body、ないタイプミス以外のr.Body –

+0

を、()意味ですか、それは不必要に文字列コピー –

+0

おっとを作成していないので、私は、受け入れられたものに優れた答えを信じています!入力ミスを修正しました - 指摘に感謝します! – JohnnyCoder

23

私はこの正確な問題で自分自身を夢中にしていました。私のJSON MarshallerとUnmarshallerは私のGo構造体に値を設定しませんでした。 https://eager.io/blog/go-and-json

"Goのすべての構造体と同様に、大文字の最初の文字があるフィールドだけがJSON Marshallerのような外部プログラムに見えることを覚えておくことが重要です。

その後、私のMarshallerとUnmarshallerは完全に機能しました!

+0

男私はあなたの仕事のこの解決の後に文字通り叫んでいた。ありがとう、ああ私の神。 – AndreaM16

+1

ありがとう!これは王位に値する –

+0

これはかなり一般的なエラーのようです:-) –

関連する問題