Can';t Json.Unmarshal到结构
我遇到了一种情况,我想通过TCP连接将消息从一台服务器传输到另一台服务器。 我在两台服务器上都创建了一个结构:Can';t Json.Unmarshal到结构,json,go,struct,tcp,Json,Go,Struct,Tcp,我遇到了一种情况,我想通过TCP连接将消息从一台服务器传输到另一台服务器。 我在两台服务器上都创建了一个结构: type DataTransferObject struct { Name string `json:"name"` Value string `json:"value"` } 和 dto := DataTransferObject{ Name: "Name", Value: name, } jsonDTO, _ := json.Marshal(
type DataTransferObject struct {
Name string `json:"name"`
Value string `json:"value"`
}
和
dto := DataTransferObject{
Name: "Name",
Value: name,
}
jsonDTO, _ := json.Marshal(dto)
connection.Write(jsonDTO)
我正在将它发送到另一台服务器。服务器接收到一条消息,但当我尝试按如下方式解组它时:
var MessageData DataTransferObject
err = json.Unmarshal(message, &MessageData)
fmt.Println(err.Error())
MessageData结构保持为零。但是,当我用
fmt.Println(string(message))
我得到如下字符串:{“Name”:“testname”,“Value”:“testvalue”} 两个项目中的结构:
type DataTransferObject struct {
Name string `json:"name"`
Value string `json:"value"`
}
这是接收的完整代码:
/**
* function for receiving a message with data from a client
**/
func (manager *ClientManager) receive(client *Client) {
for {
message := make([]byte,1024)
length, err := client.socketConnection.Read(message)
if err != nil {
fmt.Println(err)
manager.unregister <- client
client.socketConnection.Close()
break
}
if length > 0 {
var MessageData DataTransferObject
err = json.Unmarshal(message, &MessageData)
fmt.Println(err.Error())
if MessageData.Name =="Name"{
manager.clientAddr[MessageData.Value] = client
manager.SendData("testMessage", "hello world!")
}else {
fmt.Println(string (message))
}
manager.broadcast <- message
}
}
}
看起来您遇到的问题是因为json.Unmarshal不处理字节数组中的字符串终止(在我看来这实际上是一个bug,如果它需要字节数组,它应该知道如何处理它)。因此,当您分配一个1024字节的缓冲区并从连接中读入它时,您将得到几个字符的数据、空字节终止符以及缓冲区其余部分的任何垃圾。这就混淆了json.Unmarshall。它实际上会抛出一个错误,如果您没有忽略错误处理,您将看到它:) 公共服务公告:如果有东西返回错误,您可能至少要打印它。等大便破了,你会感谢自己的 有几种方法可以处理它,但标准似乎是使用bufio库。下面是一个完整的工作示例,通过TCP连接发送JSON记录并将其反序列化为结构(是的,此代码完全忽略所有错误) 包干管
import (
"bufio"
"encoding/json"
"fmt"
"net"
"time"
)
type DataTransferObject struct {
Name string `json:"name"`
Value string `json:"value"`
}
func server(l net.Listener) {
for {
c, _ := l.Accept()
data, _ := bufio.NewReader(c).ReadBytes(0)
fmt.Printf("read %v bytes from the server\n", len(data))
fmt.Println("data: ", string(data))
var obj DataTransferObject
err := json.Unmarshal(data, &obj)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Got object %+v\n", obj)
}
}
func main() {
l, _ := net.Listen("tcp", ":8080")
defer l.Close()
go server(l)
con, _ := net.Dial("tcp", "localhost:8080")
data := []byte(`{"name": "Mad Wombat", "value": "Awesome Go Marsupial"}`)
count, _ := con.Write(data)
fmt.Printf("written %v bytes to the server\n", count)
con.Close()
time.Sleep(time.Second) // wait for the server to do its thing
}
您的结构标记无效。重新阅读文档。你应该有
json:“name”
(带引号,没有空格)。@Adrian以前有过,现在改回了json:“name”,但没有改变我的问题。那么问题就出在你没有向我们展示的东西上,因为如前所述,它工作正常:我编辑代码是因为我自己发现了一些错误,这就是真正的代码。但问题仍然没有解决。但现在我收到了一条“顶层值”消息之后的“无效字符”\x00”,但仍然可以使用fmt.Println(string(message))打印消息。我的一个朋友刚刚发现,json.marshal和unmarshal在发送数据之前也可以工作。只有在TCP连接的另一端出现错误。希望我没有弄乱任何名称声明。刚刚更改了一些变量名。我被这段代码弄糊涂了。您是否尝试在连接的同一端读写?您在哪里侦听端口4242并接受传入的连接?我无法发布我的完整项目,因为我已经工作了数周。这就是为什么它可能令人困惑的问题。第一个是我的Web服务器,它的主要功能是监听端口4242上的tcp连接(当然除了Web应用程序的端口)。当我收到一条消息时,我会将客户机映射到一个名称,以便以后识别客户机。出于测试原因,我正在尝试向客户端发送一条消息,该消息应该可以通过名称找到。“基本上就是这样。”MadWombat还可以发送消息。发送[]字节并接收它完全没有问题,可以解析为字符串。但是当涉及到json时,它就不起作用了。我读到可能是因为缓冲区的大小?“message:=make([]字节,1024)”“Unmarshall实际上会抛出一个错误,如果您没有忽略错误处理,您会看到它:)”如果错误是:“顶层值后面的无效字符'\x00',而不是我在注释部分写的。谢谢你,我会试试这个然后回答,就是那个。看起来json.Unmarshal是虚伪的,它需要一个字节数组,但秘密地希望字节数组是一个完整的字符串。因此,当它遇到一个空字符时,它会发出嘶嘶声。它确实起作用了!但现在我有另一个错误需要修复:-D“读取tcp[::1]:4242->[::1]:49634:wsarecv:(…)”,但我会解决这个问题!
import (
"bufio"
"encoding/json"
"fmt"
"net"
"time"
)
type DataTransferObject struct {
Name string `json:"name"`
Value string `json:"value"`
}
func server(l net.Listener) {
for {
c, _ := l.Accept()
data, _ := bufio.NewReader(c).ReadBytes(0)
fmt.Printf("read %v bytes from the server\n", len(data))
fmt.Println("data: ", string(data))
var obj DataTransferObject
err := json.Unmarshal(data, &obj)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Got object %+v\n", obj)
}
}
func main() {
l, _ := net.Listen("tcp", ":8080")
defer l.Close()
go server(l)
con, _ := net.Dial("tcp", "localhost:8080")
data := []byte(`{"name": "Mad Wombat", "value": "Awesome Go Marsupial"}`)
count, _ := con.Write(data)
fmt.Printf("written %v bytes to the server\n", count)
con.Close()
time.Sleep(time.Second) // wait for the server to do its thing
}