解码JSON时出现错误

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

Error when decoding JSON

问题

我最近第一次尝试使用GO进行实验。

我有一个HTML表单,将其值传递给服务器。然后,该服务器提取表单键/值并将它们放入JSON中。然后将此JSON发送到另一个服务器。

问题是:当第二个服务器尝试解码JSON时,我收到以下错误:

Error decoding JSON: json: cannot unmarshal string into Go value of type main.NewContainerJSON

1:原始HTML表单

<form method="post" action="http://127.0.0.1:8080/new-user" autocomplete="on">
	<table>
		<tr>
			<td colspan="2"><h1>Container Configuration</h1></td>
		</tr>
		<tr>
			<td><h2>Container Name</h2></td>
			<td><input type="text" name="containerName" placeholder="My Container Name" required /></td>
		</tr>
		<tr>
			<td><h2>Base Server</h2></td>
			<td>
				<select name="BaseServer">
					<option value="Ubuntu 14.04">Ubuntu 14.04</option>
			</td>
		</tr>
		<tr>
			<td><h2>Content Management System</h2></td>
			<td>
				<select name="CMS">
					<option value="Wordpress">Wordpress</option>
			</td>
		</tr>
		<tr>
			<td><h2>Website Name</h2></td>
			<td><input type="text" name="websiteName" placeholder="mysite.com" required /></td>
		</tr>
		<tr>
			<td><h2>New Root Database Password</h2> </td>
			<td><input type="password" name="dbRootPWD" placeholder="password" required /></td>
		</tr>
		<tr>
			<td><h2>Database Admin Username</h2></td>
			<td><input type="text" name="dbAdminUname" placeholder="Admin" required /></td>
		</tr>
		<tr>
			<td><h2>Database Admin Password</h2></td>
			<td><input type="password" name="dbAdminPwd" placeholder="password" required /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="submit"></td>
		</tr>
	</table>	
</form>

2:第一个服务器的代码

package main

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

type newContainerJSON struct {
	ContainerName string
	BaseServer    string
	CMS           string
	WebsiteName   string
	DBrootPWD     string
	DBadminUname  string
	DBadminPWD    string
}

func newUser(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()

	cName := r.FormValue("containerName")
	sName := r.FormValue("BaseServer")
	cmsName := r.FormValue("CMS")
	wsName := r.FormValue("websiteName")
	dbrootPwd := r.FormValue("dbRootPWD")
	dbadmName := r.FormValue("dbAdminUname")
	dbamdpwdName := r.FormValue("dbAdminPwd")

	c := newContainerJSON{
		ContainerName: cName,
		BaseServer:    sName,
		CMS:           cmsName,
		WebsiteName:   wsName,
		DBrootPWD:     dbrootPwd,
		DBadminUname:  dbadmName,
		DBadminPWD:    dbamdpwdName,
	}

	d, _ := json.Marshal(c)
	s := string(d)
	fmt.Println(s)

	conn, err := net.Dial("tcp", "127.0.0.1:8081")
	checkError(err)

	encoder := json.NewEncoder(conn)

	encoder.Encode(d)
}

func main() {
	http.HandleFunc("/new-user", newUser)
	err := http.ListenAndServe(":8080", nil) // setting listening port
	checkError(err)
}

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
	}
}

3:第二个服务器的代码

package main

import (
	"fmt"
	"net"
	"encoding/json"
)

type NewContainerJSON struct {
	ContainerName string `json:",string"`
	BaseServer    string `json:",string"`
	CMS           string `json:",string"`
	WebsiteName   string `json:",string"`
	DBrootPWD     string `json:",string"`
	DBadminUname  string `json:",string"`
	DBadminPWD    string `json:",string"`
}

func main() {

	service := "127.0.0.1:8081"
	tcpAddr, err := net.ResolveTCPAddr("tcp", service)
	checkError(err)

	listener, err := net.ListenTCP("tcp", tcpAddr)
	checkError(err)

	conn, err := listener.Accept()
	checkError(err)

	decoder := json.NewDecoder(conn)

	var b NewContainerJSON
	err = decoder.Decode(&b)
	checkError(err)

	fmt.Println(b)

	conn.Close() // we're finished

}

func checkError(err error) {
	if err != nil {
		fmt.Println("An error occurred: ", err.Error())

	}
}

在第二个服务器的代码中,以下代码导致错误:

var b NewContainerJSON
err = decoder.Decode(&b)
checkError(err)

fmt.Println(b)

我怀疑我没有正确解码JSON,或者我遗漏了一些非常明显的东西。

英文:

I have been experimenting with GO for the first time, over the last few days.

I have a HTML form that passes it's values to a server. This server in turn extracts the form keys/ values and places them inside a JSON. This JSON is then sent to another server.

The issue is: I get the following error when the second server attempts to decode the JSON:

Error decoding JSON: json: cannot unmarshal string into Go value of type main.NewContainerJSON

1: The original HTML form

&lt;form method=&quot;post&quot; action=&quot;http://127.0.0.1:8080/new-user&quot; autocomplete =&quot;on&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&lt;h1&gt;Container Configuration&lt;/h1&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Container Name&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;containerName&quot; placeholder = &quot;My Container Name&quot; required /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Base Server&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;
&lt;select name=&quot;BaseServer&quot;&gt;
&lt;option value=&quot;Ubuntu 14.04&quot;&gt;Ubuntu 14.04&lt;/option&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Content Management System&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;
&lt;select name=&quot;CMS&quot;&gt;
&lt;option value=&quot;Wordpress&quot;&gt;Wordpress&lt;/option&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Website Name&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;websiteName&quot; placeholder = &quot;mysite.com&quot; required /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;New Root Database Password&lt;/h2&gt; &lt;/td&gt;
&lt;td&gt;&lt;input type = &quot;password&quot; name = &quot;dbRootPWD&quot; placeholder = &quot;password&quot; required /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Database Admin Username&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type = &quot;text&quot; name = &quot;dbAdminUname&quot; placeholder = &quot;Admin&quot; required /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;h2&gt;Database Admin Password&lt;/h2&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type = &quot;password&quot; name = &quot;dbAdminPwd&quot; placeholder = &quot;password&quot; required /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;input type = &quot;submit&quot; value = &quot;submit&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;	

</form>

2: The first servers code

package main
import (
&quot;fmt&quot;
&quot;encoding/json&quot;
&quot;net&quot;
&quot;net/http&quot;
)
type newContainerJSON struct {
ContainerName string
BaseServer string
CMS string
WebsiteName string
DBrootPWD string
DBadminUname string
DBadminPWD string
}
func newUser(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
cName := r.FormValue(&quot;containerName&quot;)
sName := r.FormValue(&quot;BaseServer&quot;)
cmsName := r.FormValue(&quot;CMS&quot;)
wsName := r.FormValue(&quot;websiteName&quot;)
dbrootPwd := r.FormValue(&quot;dbRootPWD&quot;)
dbadmName := r.FormValue(&quot;dbAdminUname&quot;)
dbamdpwdName := r.FormValue(&quot;dbAdminPwd&quot;) 
c := newContainerJSON {
ContainerName: cName,
BaseServer: sName,
CMS: cmsName,
WebsiteName: wsName,
DBrootPWD: dbrootPwd,
DBadminUname: dbadmName,
DBadminPWD: dbamdpwdName,
}
d, _ := json.Marshal(c)
s := string(d)
fmt.Println(s)
conn, err := net.Dial(&quot;tcp&quot;, &quot;127.0.0.1:8081&quot;)
checkError(err)
encoder := json.NewEncoder(conn)
encoder.Encode(d) 
}
func main() {
http.HandleFunc(&quot;/new-user&quot;, newUser)
err := http.ListenAndServe(&quot;:8080&quot;, nil) // setting listening port
checkError(err)
}
func checkError(err error) {
if err != nil {
fmt.Println(&quot;Fatal error &quot;, err.Error())
}
}

3: The second servers code:

package main
import (
&quot;fmt&quot;
&quot;net&quot;
&quot;encoding/json&quot;
)
type NewContainerJSON struct {
ContainerName string	`json:&quot;,string&quot;`
BaseServer string		`json:&quot;,string&quot;`
CMS string				`json:&quot;,string&quot;`
WebsiteName string		`json:&quot;,string&quot;`
DBrootPWD string		`json:&quot;,string&quot;`
DBadminUname string		`json:&quot;,string&quot;`
DBadminPWD string		`json:&quot;,string&quot;`
}
func main() {
service := &quot;127.0.0.1:8081&quot;
tcpAddr, err := net.ResolveTCPAddr(&quot;tcp&quot;, service)
checkError(err)
listener, err := net.ListenTCP(&quot;tcp&quot;, tcpAddr)
checkError(err)
conn, err := listener.Accept()
checkError(err)
decoder := json.NewDecoder(conn)
var b NewContainerJSON
err = decoder.Decode(&amp;b)
checkError(err)
fmt.Println(b)
conn.Close() // we&#39;re finished
}
func checkError(err error) {
if err != nil {
fmt.Println(&quot;An error occurred: &quot;, err.Error())
}
}

The error occurs with following code in the second servers code

var b NewContainerJSON
err = decoder.Decode(&amp;b)
checkError(err)
fmt.Println(b)

I suspect I am not decoding the JSON properly or I am missing something very obvious.

答案1

得分: 3

第一个服务器对值进行了双重编码。结果是一个字符串。

d, _ := json.Marshal(c) // d 是包含 JSON 的 []byte
...
encoder.Encode(d)  // encoder 将 []byte 的 base64 编码作为 JSON 字符串写入

将代码更改为:

conn, err := net.Dial("tcp", "127.0.0.1:8081")
if err != nil {
// 处理错误
}
encoder := json.NewEncoder(conn)
if err := encoder.Encode(c); err != nil {
// 处理错误
}
英文:

The first server is double encoding the value. The result is a string.

d, _ := json.Marshal(c) // d is []byte containing the JSON
...
encoder.Encode(d)  // encoder writes base64 encoding of []byte as JSON string

Change the code to:

conn, err := net.Dial(&quot;tcp&quot;, &quot;127.0.0.1:8081&quot;)
if err != nil {
// handle error
}
encoder := json.NewEncoder(conn)
if err := encoder.Encode(c); err != nil {
// handle error
}

答案2

得分: 1

当你执行encoder.Encode(d)时,你正在对前一步骤的编组结果进行编码。因此,当你解码它时,你得到的不是Go对象,而是一个字符串。

相反,你可以执行encoder.Encode(c)(直接对对象c进行编码)。

这应该能帮助你理解:http://play.golang.org/p/qNxqOJcj_a

英文:

When you do encoder.Encode(d), you are encoding the marshaled result from previous step. So when you decode it back you don't get the go object, but a string.

Instead you can do, encoder.Encode(c). (Directly encode the object c).

This should help you understand: http://play.golang.org/p/qNxqOJcj_a

huangapple
  • 本文由 发表于 2016年3月31日 09:14:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/36322527.html
匿名

发表评论

匿名网友

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

确定