Go – 编码嵌套结构

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

Go - Encode nested structure

问题

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

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

我想要使用JSON数据。

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

一些代码:

  1. type ChatroomData struct {
  2. Token string `json:"token"`
  3. Chatroom *Chatroom `json:"chatroom"`
  4. }
  5. type Message struct {
  6. Token string `json:"token,omitempty"`
  7. Type string `json:"type"`
  8. Author string `json:"author"`
  9. Content string `json:"content"`
  10. Chatroom string `json:"chatroom"`
  11. }
  12. type Messages []Message

聊天室结构:

  1. type Chatroom struct {
  2. Name string `json:"name"`
  3. Users []User `json:"users"`
  4. Messages Messages `json:"messages"`
  5. Hub *WsHub `json:"-"`
  6. }
  7. type Chatrooms map[string]*Chatroom
  8. type User struct {
  9. Username string `json:"username"`
  10. Token string `json:"-"`
  11. }
  12. type Users []User

启动聊天室:

  1. func (s *Server) startMainChatroom() {
  2. s.Chatrooms["main"] = &Chatroom{
  3. Name: "main",
  4. Users: make([]User, 0),
  5. Messages: make([]Message, 0),
  6. Hub: NewHub(),
  7. }
  8. go s.Chatrooms["main"].Hub.Run()
  9. }

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

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

向客户端发送数据:

  1. func (u *User) SendChatroomData(w http.ResponseWriter, c *Chatroom, status int) {
  2. chatroomData := ChatroomData{Token: u.Token, Chatroom: c}
  3. w.Header().Set("Access-Control-Allow-Origin", "*")
  4. w.Header().Set("Access-Control-Allow-Headers", "accept, authorization")
  5. w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
  6. w.WriteHeader(status)
  7. if err := json.NewEncoder(w).Encode(&chatroomData); err != nil {
  8. panic(err)
  9. }
  10. }

打印的结果是:

  1. {
  2. "token": "a638ed3ba0c30ba3d0810fc79e12a50a",
  3. "chatroom": {
  4. "name": "main",
  5. "users": [{}, {}],
  6. "messages": []
  7. }
  8. }

有两个用户和三条消息被发送。如果我使用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 :

  1. type(
  2. ChatroomData struct {
  3. Token string `json:"token"`
  4. Chatroom *Chatroom `json:"chatroom"`
  5. }
  6. Message struct {
  7. Token string `json:"token,omitempty"`
  8. Type string `json:"type"`
  9. Author string `json:"author"`
  10. Content string `json:"content"`
  11. Chatroom string `json:"chatroom"`
  12. }
  13. Messages []Message
  14. )

The chatroom struct :

  1. Chatroom struct {
  2. Name string `json:"name"`
  3. Users []User `json:"users"`
  4. Messages Messages `json:"messages"`
  5. Hub *WsHub `json:"-"`
  6. }
  7. Chatrooms map[string]*Chatroom
  8. User struct {
  9. username string `json:"username"`
  10. token string `json:"-"`
  11. }
  12. Users []User

Start the chatroom :

  1. func (s *Server) startMainChatroom() {
  2. s.Chatrooms["main"] = &Chatroom{
  3. Name: "main",
  4. Users: make([]User, 0),
  5. Messages: make([]Message, 0),
  6. Hub: NewHub(),
  7. }
  8. go s.Chatrooms["main"].Hub.Run()
  9. }

The way to append messages to the chatroom :

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

Send data to the client :

  1. func (u *User) SendChatroomData(w http.ResponseWriter, c *Chatroom, status int) {
  2. chatroomData := ChatroomData{Token: u.token, Chatroom: c}
  3. w.Header().Set("Access-Control-Allow-Origin", "*")
  4. w.Header().Set("Access-Control-Allow-Headers", "accept, authorization")
  5. w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
  6. w.WriteHeader(status)
  7. if err := json.NewEncoder(w).Encode(&chatroomData); err != nil {
  8. panic(err)
  9. }
  10. }

The printed result is :

  1. {
  2. "token":"a638ed3ba0c30ba3d0810fc79e12a50a",
  3. "chatroom":{
  4. "name":"main",
  5. "users":[{},{}],
  6. "messages":[]
  7. }
  8. }

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:

确定