无法将表单正确序列化为 JSON。

huangapple go评论85阅读模式
英文:

Can't properly serialize forms into a json

问题

我正在尝试使用Golang创建一个Web应用程序,允许您在不同的表单中输入收据的详细信息,然后将这些表单输入序列化为JSON对象。然而,我在序列化表单时遇到了问题,因为每当我尝试“提交”收据时,都会出现错误。

这是main.go文件的内容:

package main

import (
	"encoding/json"
	"html/template"
	"log"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
)

type Item struct {
	ShortDescription string `json:"shortDescription"`
	Price            string `json:"price"`
}

type Receipt struct {
	Retailer     string `json:"retailer"`
	PurchaseDate string `json:"purchaseDate"`
	PurchaseTime string `json:"purchaseTime"`
	Items        []Item `json:"items"`
	Total        string `json:"total"`
	ReceiptID    int    `json:"receiptID"`
}

var receiptIDCounter int

var receipts = make(map[int]Receipt)

func main() {
	r := mux.NewRouter()

	r.HandleFunc("/", homeHandler).Methods("GET")
	r.HandleFunc("/submit", submitHandler).Methods("POST")
	r.HandleFunc("/receipt/{id}", receiptHandler).Methods("GET")

	http.Handle("/", r)

	log.Fatal(http.ListenAndServe(":8080", nil))
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("templates/home.html")
	if err != nil {
		log.Println(err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	err = t.Execute(w, nil)
	if err != nil {
		log.Println(err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
	}
}

func submitHandler(w http.ResponseWriter, r *http.Request) {
	decoder := json.NewDecoder(r.Body)

	var receipt Receipt
	err := decoder.Decode(&receipt)
	if err != nil {
		log.Println(err)
		http.Error(w, "Bad request", http.StatusBadRequest)
		return
	}

	receiptIDCounter++
	receipt.ReceiptID = receiptIDCounter
	receipts[receipt.ReceiptID] = receipt

	jsonResponse, err := json.Marshal(map[string]int{"receiptID": receipt.ReceiptID})
	if err != nil {
		log.Println(err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(jsonResponse)
}

func receiptHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		log.Println(err)
		http.Error(w, "Bad request", http.StatusBadRequest)
		return
	}

	receipt, exists := receipts[id]
	if !exists {
		http.NotFound(w, r)
		return
	}

	t, err := template.ParseFiles("templates/receipt.html")
	if err != nil {
		log.Println(err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
		return
	}

	err = t.Execute(w, receipt)
	if err != nil {
		log.Println(err)
		http.Error(w, "Internal server error", http.StatusInternalServerError)
	}
}

这是home.html文件,是我的主页的HTML代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Receipt Input Form</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <h1>Receipt Input Form</h1>
    <form id="receipt-form">
        <label>Retailer:</label>
        <input type="text" name="retailer" required><br><br>
        
        <label>Purchase Date:</label>
        <input type="date" name="purchaseDate" required><br><br>
        
        <label>Purchase Time:</label>
        <input type="time" name="purchaseTime" required><br><br>
        
        <div id="items">
            <div class="item">
                <label>Short Description:</label>
                <input type="text" name="shortDescription[]" required>
                
                <label>Price:</label>
                <input type="number" name="price[]" step="0.01" min="0" required>
            </div>
        </div>
        <button type="button" id="add-item-btn">Add Item</button><br><br>
        
        <label>Total:</label>
        <input type="number" name="total" step="0.01" min="0" required><br><br>
        
        <button type="submit">Submit</button>
    </form>

    <script>
        $(document).ready(function() {
            var itemCount = 1;
            $('#add-item-btn').click(function() {
                itemCount++;
                var newItem = '<div class="item"><label>Short Description:</label>' +
                    '<input type="text" name="shortDescription[]" required>' +
                    '<label>Price:</label>' +
                    '<input type="number" name="price[]" step="0.01" min="0" required>' +
                    '<button type="button" class="remove-item-btn">Remove Item</button>' +
                    '</div>';
                $('#items').append(newItem);
            });
            
            $(document).on('click', '.remove-item-btn', function() {
                $(this).parent().remove();
                itemCount--;
            });
            
            $('#receipt-form').submit(function(event) {
                event.preventDefault();
                var form = $(this).serializeArray();
                var items = [];
                $('.item').each(function() {
                    var item = {};
                    item.shortDescription = $(this).find('input[name="shortDescription[]"]').val();
                    item.price = $(this).find('input[name="price[]"]').val();
                    items.push(item);
                });
                form.push({ name: "items", value: JSON.stringify(items) });
                $.ajax({
                    type: "POST",
                    url: "/submit",
                    data: form,
                    success: function(response) {
                        window.location.href = "/receipt?id=" + response.receiptID;
                    },
                    error: function(xhr, status, error) {
                        console.log(xhr.responseText);
                    }
                });
            });
        });
    </script>
</body>
</html>

这是receipt.html文件,是收据提交后显示的HTML代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Receipt Details</title>
</head>
<body>
    <h1>Receipt Details</h1>
    <ul>
        <li>Retailer: {{.Retailer}}</li>
        <li>Purchase Date: {{.PurchaseDate}}</li>
        <li>Purchase Time: {{.PurchaseTime}}</li>
        <li>Items:</li>
        <ul>
            {{range .Items}}
            <li>{{.ShortDescription}} - {{.Price}}</li>
            {{end}}
        </ul>
        <li>Total: {{.Total}}</li>
    </ul>
</body>
</html>

我尝试了不同的序列化方式,但没有得到任何有效的结果。当我填写收据表单并点击提交时,我希望能够跳转到显示该收据唯一详细信息的收据页面。然而,我一直收到错误消息,最近的一个错误消息是:invalid character 'r' looking for beginning of value

英文:

I'm trying to make a web application in golang that allows you enter in details of a receipt into different forms, then those form inputs get serialized into a json object. However I'm having trouble serializing the forms because whenever I try to "submit" my receipt, I get an error.

This is the main.go

package main
import (
&quot;encoding/json&quot;
&quot;html/template&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;strconv&quot;
&quot;github.com/gorilla/mux&quot;
)
type Item struct {
ShortDescription string `json:&quot;shortDescription&quot;`
Price            string `json:&quot;price&quot;`
}
type Receipt struct {
Retailer     string `json:&quot;retailer&quot;`
PurchaseDate string `json:&quot;purchaseDate&quot;`
PurchaseTime string `json:&quot;purchaseTime&quot;`
Items        []Item `json:&quot;items&quot;`
Total        string `json:&quot;total&quot;`
ReceiptID    int    `json:&quot;receiptID&quot;`
}
var receiptIDCounter int
var receipts = make(map[int]Receipt)
func main() {
r := mux.NewRouter()
r.HandleFunc(&quot;/&quot;, homeHandler).Methods(&quot;GET&quot;)
r.HandleFunc(&quot;/submit&quot;, submitHandler).Methods(&quot;POST&quot;)
r.HandleFunc(&quot;/receipt/{id}&quot;, receiptHandler).Methods(&quot;GET&quot;)
http.Handle(&quot;/&quot;, r)
log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles(&quot;templates/home.html&quot;)
if err != nil {
log.Println(err)
http.Error(w, &quot;Internal server error&quot;, http.StatusInternalServerError)
return
}
err = t.Execute(w, nil)
if err != nil {
log.Println(err)
http.Error(w, &quot;Internal server error&quot;, http.StatusInternalServerError)
}
}
func submitHandler(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var receipt Receipt
err := decoder.Decode(&amp;receipt)
if err != nil {
log.Println(err)
http.Error(w, &quot;Bad request&quot;, http.StatusBadRequest)
return
}
receiptIDCounter++
receipt.ReceiptID = receiptIDCounter
receipts[receipt.ReceiptID] = receipt
jsonResponse, err := json.Marshal(map[string]int{&quot;receiptID&quot;: receipt.ReceiptID})
if err != nil {
log.Println(err)
http.Error(w, &quot;Internal server error&quot;, http.StatusInternalServerError)
return
}
w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
w.Write(jsonResponse)
}
func receiptHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars[&quot;id&quot;])
if err != nil {
log.Println(err)
http.Error(w, &quot;Bad request&quot;, http.StatusBadRequest)
return
}
receipt, exists := receipts[id]
if !exists {
http.NotFound(w, r)
return
}
t, err := template.ParseFiles(&quot;templates/receipt.html&quot;)
if err != nil {
log.Println(err)
http.Error(w, &quot;Internal server error&quot;, http.StatusInternalServerError)
return
}
err = t.Execute(w, receipt)
if err != nil {
log.Println(err)
http.Error(w, &quot;Internal server error&quot;, http.StatusInternalServerError)
}
}

This is my home.html which the html for my homepage

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Receipt Input Form&lt;/title&gt;
&lt;script src=&quot;https://code.jquery.com/jquery-3.6.0.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Receipt Input Form&lt;/h1&gt;
&lt;form id=&quot;receipt-form&quot;&gt;
&lt;label&gt;Retailer:&lt;/label&gt;
&lt;input type=&quot;text&quot; name=&quot;retailer&quot; required&gt;&lt;br&gt;&lt;br&gt;
&lt;label&gt;Purchase Date:&lt;/label&gt;
&lt;input type=&quot;date&quot; name=&quot;purchaseDate&quot; required&gt;&lt;br&gt;&lt;br&gt;
&lt;label&gt;Purchase Time:&lt;/label&gt;
&lt;input type=&quot;time&quot; name=&quot;purchaseTime&quot; required&gt;&lt;br&gt;&lt;br&gt;
&lt;div id=&quot;items&quot;&gt;
&lt;div class=&quot;item&quot;&gt;
&lt;label&gt;Short Description:&lt;/label&gt;
&lt;input type=&quot;text&quot; name=&quot;shortDescription[]&quot; required&gt;
&lt;label&gt;Price:&lt;/label&gt;
&lt;input type=&quot;number&quot; name=&quot;price[]&quot; step=&quot;0.01&quot; min=&quot;0&quot; required&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;button type=&quot;button&quot; id=&quot;add-item-btn&quot;&gt;Add Item&lt;/button&gt;&lt;br&gt;&lt;br&gt;
&lt;label&gt;Total:&lt;/label&gt;
&lt;input type=&quot;number&quot; name=&quot;total&quot; step=&quot;0.01&quot; min=&quot;0&quot; required&gt;&lt;br&gt;&lt;br&gt;
&lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
&lt;/form&gt;
&lt;script&gt;
$(document).ready(function() {
var itemCount = 1;
$(&#39;#add-item-btn&#39;).click(function() {
itemCount++;
var newItem = &#39;&lt;div class=&quot;item&quot;&gt;&lt;label&gt;Short Description:&lt;/label&gt;&#39; +
&#39;&lt;input type=&quot;text&quot; name=&quot;shortDescription[]&quot; required&gt;&#39; +
&#39;&lt;label&gt;Price:&lt;/label&gt;&#39; +
&#39;&lt;input type=&quot;number&quot; name=&quot;price[]&quot; step=&quot;0.01&quot; min=&quot;0&quot; required&gt;&#39; +
&#39;&lt;button type=&quot;button&quot; class=&quot;remove-item-btn&quot;&gt;Remove Item&lt;/button&gt;&#39; +
&#39;&lt;/div&gt;&#39;;
$(&#39;#items&#39;).append(newItem);
});
$(document).on(&#39;click&#39;, &#39;.remove-item-btn&#39;, function() {
$(this).parent().remove();
itemCount--;
});
$(&#39;#receipt-form&#39;).submit(function(event) {
event.preventDefault();
var form = $(this).serializeArray();
var items = [];
$(&#39;.item&#39;).each(function() {
var item = {};
item.shortDescription = $(this).find(&#39;input[name=&quot;shortDescription[]&quot;]&#39;).val();
item.price = $(this).find(&#39;input[name=&quot;price[]&quot;]&#39;).val();
items.push(item);
});
form.push({ name: &quot;items&quot;, value: JSON.stringify(items) });
$.ajax({
type: &quot;POST&quot;,
url: &quot;/submit&quot;,
data: form,
success: function(response) {
window.location.href = &quot;/receipt?id=&quot; + response.receiptID;
},
error: function(xhr, status, error) {
console.log(xhr.responseText);
}
});
});
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

This is my receipt.html which is the html for the receipt page after the receipt gets submitted.

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Receipt Details&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Receipt Details&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Retailer: {{.Retailer}}&lt;/li&gt;
&lt;li&gt;Purchase Date: {{.PurchaseDate}}&lt;/li&gt;
&lt;li&gt;Purchase Time: {{.PurchaseTime}}&lt;/li&gt;
&lt;li&gt;Items:&lt;/li&gt;
&lt;ul&gt;
{{range .Items}}
&lt;li&gt;{{.ShortDescription}} - {{.Price}}&lt;/li&gt;
{{end}}
&lt;/ul&gt;
&lt;li&gt;Total: {{.Total}}&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;

I've tried different ways of serialization but haven't got anything to work. When I fill out the forms for the receipt then hit submit, I expect that I get taken to the receipt page showing unique details for that receipt. However I'm just getting an error, my most recent one being this:
invalid character &#39;r&#39; looking for beginning of value

答案1

得分: 0

请将您的home.html更新如下。我将提交请求的Content-Type更改为application/json,因为服务器中的submitHandler正在寻找一个JSON

$(&#39;#receipt-form&#39;).submit(function(event) {
    event.preventDefault();
    
    var form = $(this).serializeArray();

    var formObject = {};
    $.each(form,
        function(i, v) {
            if (v.name != &quot;price[]&quot; &amp;&amp; v.name != &quot;shortDescription[]&quot;) {
                formObject[v.name] = v.value;
            }
        });

    var items = [];
    $(&#39;.item&#39;).each(function() {
        var item = {};
        item.shortDescription = $(this).find(&#39;input[name=&quot;shortDescription[]&quot;]&#39;).val();
        item.price = $(this).find(&#39;input[name=&quot;price[]&quot;]&#39;).val();
        items.push(item);
    });

    formObject[&quot;items&quot;] = items;

    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/submit&quot;,
        contentType: &quot;application/json; charset=utf-8&quot;,
        dataType: &quot;json&quot;,
        data: JSON.stringify(formObject),
        success: function(response) {
            window.location.href = &quot;/receipt?id=&quot; + response.receiptID;
        },
        error: function(xhr, status, error) {
            console.log(xhr.responseText);
        }
    });
});

英文:

Please update your home.html as below. I changed submit request Content-Type to application/json because submitHandler in the server is looking for an JSON.

$(&#39;#receipt-form&#39;).submit(function(event) {
    event.preventDefault();
    
    var form = $(this).serializeArray();

    var formObject = {};
    $.each(form,
        function(i, v) {
            if (v.name != &quot;price[]&quot; &amp;&amp; v.name != &quot;shortDescription[]&quot;) {
                formObject[v.name] = v.value;
            }
        });

    var items = [];
    $(&#39;.item&#39;).each(function() {
        var item = {};
        item.shortDescription = $(this).find(&#39;input[name=&quot;shortDescription[]&quot;]&#39;).val();
        item.price = $(this).find(&#39;input[name=&quot;price[]&quot;]&#39;).val();
        items.push(item);
    });

    formObject[&quot;items&quot;] = items;

    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/submit&quot;,
        contentType: &quot;application/json; charset=utf-8&quot;,
        dataType: &quot;json&quot;,
        data: JSON.stringify(formObject),
        success: function(response) {
            window.location.href = &quot;/receipt?id=&quot; + response.receiptID;
        },
        error: function(xhr, status, error) {
            console.log(xhr.responseText);
        }
    });
});

huangapple
  • 本文由 发表于 2023年3月18日 08:21:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75773164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定