Go – 编码嵌套结构

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

Go - Encode nested structure

问题

我正在修改http://gary.burd.info/go-websocket-chat的扩展。

这个示例通过Websockets发送原始文本。

我想要使用JSON数据。

我在Go代码中定义了一些结构,但是当我将其转换为JSON并写入客户端时,嵌套的结构不在结果中。

一些代码:

type ChatroomData struct {
    Token    string    `json:"token"`
    Chatroom *Chatroom `json:"chatroom"`
}
type Message struct {
    Token    string `json:"token,omitempty"`
    Type     string `json:"type"`
    Author   string `json:"author"`
    Content  string `json:"content"`
    Chatroom string `json:"chatroom"`
}
type Messages []Message

聊天室结构:

type Chatroom struct {
    Name     string   `json:"name"`
    Users    []User   `json:"users"`
    Messages Messages `json:"messages"`
    Hub      *WsHub   `json:"-"`
}
type Chatrooms map[string]*Chatroom
type User struct {
    Username string `json:"username"`
    Token    string `json:"-"`
}
type Users []User

启动聊天室:

func (s *Server) startMainChatroom() {
    s.Chatrooms["main"] = &Chatroom{
        Name:     "main",
        Users:    make([]User, 0),
        Messages: make([]Message, 0),
        Hub:      NewHub(),
    }
    go s.Chatrooms["main"].Hub.Run()
}

将消息添加到聊天室的方法:

message := Message{}
json.Unmarshal([]byte(data), &message)
message.Token = ""
message.Type = "message"
chatroom.Messages = append(chatroom.Messages, message)

向客户端发送数据:

func (u *User) SendChatroomData(w http.ResponseWriter, c *Chatroom, status int) {
    chatroomData := ChatroomData{Token: u.Token, Chatroom: c}

    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "accept, authorization")
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
    w.WriteHeader(status)
    if err := json.NewEncoder(w).Encode(&chatroomData); err != nil {
        panic(err)
    }
}

打印的结果是:

{
    "token": "a638ed3ba0c30ba3d0810fc79e12a50a",
    "chatroom": {
        "name": "main",
        "users": [{}, {}],
        "messages": []
    }
}

有两个用户和三条消息被发送。如果我使用fmt.Printf("%v\n", chatroom.Messages),我可以正确地获取这三条消息。对于用户也是一样,数据在转储时是存在的。

有很多奇怪的地方:

  • 为什么messages键保持为空?
  • 为什么users键不为空,但切片项为空?(由Mike Reedell解决)

谢谢你的帮助,如果需要,可以继续询问更多的代码。希望我的帖子还不算太长(也不要有太多的英语错误X))!

英文:

I'm working on an extension of http://gary.burd.info/go-websocket-chat.

This example sends raw text through websockets.

I want to use JSON data instead.

I did some structures in my Go code, but when I convert it to JSON to write it to the client, the nested structures are not in the result.

Some code :

type(
    ChatroomData struct {
    	Token string `json:"token"`
    	Chatroom *Chatroom `json:"chatroom"`
	}
	Message struct {
		Token string `json:"token,omitempty"`
    	Type string `json:"type"`
    	Author string `json:"author"`
	    Content string `json:"content"`
	    Chatroom string `json:"chatroom"`
    }
    Messages []Message
)

The chatroom struct :

Chatroom struct {
	Name string `json:"name"`
	Users []User `json:"users"`
	Messages Messages `json:"messages"`
	Hub *WsHub `json:"-"`
}
Chatrooms map[string]*Chatroom
User struct {
	username string `json:"username"`
	token string `json:"-"`
}
Users []User

Start the chatroom :

func (s *Server) startMainChatroom() {
    s.Chatrooms["main"] = &Chatroom{
	    Name: "main",
    	Users: make([]User, 0),
    	Messages: make([]Message, 0),
    	Hub: NewHub(),
    }
    go s.Chatrooms["main"].Hub.Run()
}

The way to append messages to the chatroom :

message := Message{}
json.Unmarshal([]byte(data), &message)
message.Token = ""
message.Type = "message"
chatroom.Messages = append(chatroom.Messages, message)

Send data to the client :

func (u *User) SendChatroomData(w http.ResponseWriter, c *Chatroom, status int) {
    chatroomData := ChatroomData{Token: u.token, Chatroom: c}

    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "accept, authorization")
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
    w.WriteHeader(status)
    if err := json.NewEncoder(w).Encode(&chatroomData); err != nil {
    	panic(err)
    }
}

The printed result is :

{
     "token":"a638ed3ba0c30ba3d0810fc79e12a50a",
     "chatroom":{
         "name":"main",
         "users":[{},{}],
         "messages":[]
     }
}

There are two users and three messages were sent. If I use fmt.Printf("%v\n", chatroom.Messages), I have the three messages correctly stored. Same for the users, data is here when I dump it.

Many things are strange :

  • Why the messages key stays empty ?
  • Why the users key doesn't, but the slice items are empty ? (solved by Mike Reedell)

Thank you for your help, don't hesitate to ask me more code if it needs to be. I hope my post isn't already too long (and not too full of english errors X)) !

答案1

得分: 1

go的JSON编组器只会输出导出的(大写字母开头)字段。User结构体中的字段是未导出的(小写字母开头),这意味着JSON编组器不知道它们的存在,无法输出它们。

英文:

The go JSON marshaler will only output exported (capitalized) fields. The field in the User struct are un-exported (lower-case), which means the JSON marshaler doesn't know they are there and can't output them.

答案2

得分: 0

问题完全出在其他地方:当我添加一些消息时,我使用的Chatroom实例没有正确绑定到s.Chatrooms["main"],这是因为我对指针的误解。

当我编排s.Chatrooms["main"]时,消息并不在其中!

感谢你的帮助!

希望这对其他Go学习者有所帮助:D

英文:

The problem was totally elsewhere : The Chatroom instance I used when adding some messages wasn't bound correctly to s.Chatrooms["main"], due to my misunderstanding of pointers.

When I marshaled s.Chatrooms["main"], the messages weren't inside !

Ty for your help !

I hope this will help some others go-learners Go – 编码嵌套结构

huangapple
  • 本文由 发表于 2015年10月28日 23:42:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/33395447.html
匿名

发表评论

匿名网友

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

确定