はじめに
質問を読んでくださりありがとうございます。
環境
mac
go 1.11
Go言語の勉強のためにWebアプリケーションを作っています。
そこでブラウザのform
からから送信されたデータをJSONに変換して、構造体にマッピングし、SQLに保存したいと考えています。しかし、ブラウザから送信されたデータをJSONに変換できず、詰まっています。
なので、まずはブラウザから送信されたデータをJSONに変換して構造体へマッピング、コンソール上に表示までができるようになりたいです。
試したこと
こちらの記事「jQueryでJSONをPOSTしてJSONのレスポンスを受け取る」を参考にしてJSONをフォームからの送信を試みましたが、失敗しました。
コード(追記 2/14)
クライアント側で、JSONデータをアラートで出すようにしたところ、クライアントから送信されたデータはJSONに変換されています。しかし、サーバー(GO)でそのJSONを受け取ってコンソールに出力しようとしたら、エラーが出ています。
レスポンスのボディを出力するようにfmt.Print(r.Body)
とした結果が下記です。
&{0xc0000aa520 <nil> <nil> false true {0 0} false false false 0x129bc20}
またそのデータをデコードした結果、出力されたエラーが下記です。
invalid character 'i' in literal true (expecting 'r')
デコードしているGoのコード
go
1func roomCreate(w http.ResponseWriter, r *http.Request) { 2 var room model.Room 3 if r.Body == nil { 4 fmt.Printf("レスポンスボディは空です。\n") 5 } 6 err := json.NewDecoder(r.Body).Decode(&room) 7 if err != nil { 8 fmt.Printf("エラー内容\n「%v」\n", err) 9 } 10 fmt.Printf("データ\n%v\n", room) 11 http.Redirect(w, r, "/room", 302) 12}
下記が全体のコードになります。
html
1 <form id="roomForm" method="POST" action="/room/new"> 2 <div class="form-group"> 3 <label>掲示板の名前</label> 4 <input type="text" name="title" id="roomTitle" class="form-control"> 5 </div> 6 <div class="form-group"> 7 <label>掲示板の説明</label> 8 <textarea name="content" rows="3" id="roomContent" class="form-control"></textarea> 9 </div> 10 <button type="submit">作成する</button> 11 </form>
js
1$(function () { 2 $("#roomForm").on('submit', function () { 3 $("#roomForm").attr("disable", true); 4 $.ajax({ 5 method: 'POST', 6 url: '/routes_room.go', 7 contentType: 'application/json', 8 dataType: 'JSON', 9 scriptCharset: 'utf-8', 10 cache: 'false', 11 timeout: 10000, 12 data: { 13 "title": $("#roomTitle").val(), 14 "content": $("#roomContent").val() 15 } 16 }) 17 .done((data) => { 18 alert(data) 19 }) 20 .fail((data) => { 21 alert(data) 22 }) 23 .always(() => { 24 $("#roomForm").attr("disable", false); 25 }); 26 }); 27}); 28 29
go
1type Room struct { 2 ID int `json:"id"` 3 Title string `json:"subject"` 4 Content string `json:"content"` 5 CreatedAt time.Time `json:"created_at"` 6} 7 8func roomCreate(w http.ResponseWriter, r *http.Request) { 9 var room model.Room 10 if r.Body == nil { 11 fmt.Printf("レスポンスボディは空です。\n") 12 } 13 err := json.NewDecoder(r.Body).Decode(&room) 14 if err != nil { 15 fmt.Printf("エラー内容\n「%v」\n", err) 16 } 17 fmt.Printf("データ\n%v\n", room) 18 http.Redirect(w, r, "/room", 302) 19} 20 21func main() { 22 mux := http.NewServeMux() 23 24 files := http.FileServer(http.Dir("assets")) 25 mux.Handle("/static/", http.StripPrefix("/static/", files)) 26 27 mux.HandleFunc("/", homeIndex) 28 mux.HandleFunc("/room/", roomIndex) 29 mux.HandleFunc("/room/new", roomCreate) 30 31 server := http.Server{ 32 Addr: "127.0.0.1:8080", 33 Handler: mux, 34 } 35 log.Fatal(server.ListenAndServe()) 36} 37
コード(追記2)
フォームから送信すると、以前まで成功していたのが$.ajax
の結果がfail
になっています。HTML, JSのコードがおかしくないかみていただけますか?
html
1// actionの指定を消しました。 enctypeを追加しました。 2 3<form id="roomForm" enctype="application/json" method="post"> 4 <div class="form-group"> 5 <label>掲示板の名前</label> 6 <input type="text" name="title" value="Go言語コミュニティ" id="roomTitle" class="form-control"> 7 </div> 8 <div class="form-group"> 9 <label>掲示板の説明</label> 10 <textarea name="content" rows="3" id="roomContent" class="form-control"></textarea> 11 </div> 12 <button type="submit">作成する</button> 13 </form>
js
1// url の指定を変えました。 2// JSON.stringify(data)を付け加えました。 3// この処理の結果はなぜかfailになります。 4$(function () { 5 $("#roomForm").on('submit', function () { 6 $("#roomForm").attr("disable", true); 7 let data = { 8 title: $("#roomTitle").val(), 9 content: $("#roomContent").val() 10 }; 11 $.ajax({ 12 method: 'post', 13 url: '/room/new', 14 data:JSON.stringify(data), 15 dataType: 'json', 16 contentType: "application/json", 17 timeout: 10000, 18 }) 19 .done((data) => { 20 alert(data); 21 }) 22 .fail((data) => { 23 alert("ERROR"); 24 alert(data); 25 }) 26 .always(() => { 27 $("#roomForm").attr("disable", false); 28 }); 29 return false 30 }); 31}); 32 33
すべてのバリデーションを通過し成功しました。
go
1func roomCreate(w http.ResponseWriter, r *http.Request) { 2 fmt.Print("roomCreate is starting!!\n") 3 // validation 4 if r.Method != "POST" { 5 fmt.Printf("メソッド : \n%v\n", r.Method) 6 w.WriteHeader(http.StatusBadRequest) 7 return 8 } 9 fmt.Print("バリデーション1 通過\n") 10 11 if r.Header.Get("Content-Type") != "application/json" { 12 fmt.Printf("レスポンスヘッダー : \n%v\n", r.Header.Get("Content-Type")) 13 w.WriteHeader(http.StatusBadRequest) 14 return 15 } 16 fmt.Print("バリデーション2 通過\n") 17 18 //To allocate slice for request body 19 length, err := strconv.Atoi(r.Header.Get("Content-Length")) 20 if err != nil { 21 fmt.Printf("コンテンツレングス : \n%v\n", r.Header.Get("Content-Length")) 22 w.WriteHeader(http.StatusInternalServerError) 23 return 24 } 25 fmt.Print("バリデーション3 通過\n") 26 27 body := make([]byte, length) 28 length, err = r.Body.Read(body) 29 if err != nil && err != io.EOF { 30 w.WriteHeader(http.StatusInternalServerError) 31 return 32 } 33 fmt.Print("バリデーション4 通過\n") 34 35 var room model.Room 36 err = json.Unmarshal(body[:length], &room) 37 if err != nil { 38 w.WriteHeader(http.StatusInternalServerError) 39 return 40 } 41 fmt.Print("バリデーション5 通過\n") 42 fmt.Printf("%v\n", room) 43 w.WriteHeader(http.StatusOK) 44 http.Redirect(w, r, "/room", 302) 45} 46
質問
なぜJSONをサーバー側で受け取れていないんでしょうか?
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/14 02:37
2019/02/14 03:50 編集
2019/02/14 13:02