我正在为Flowdock API编写一个go客户端。他们的Message for Message有许多属性,其中两个是Event
和Content
当Event = message
时,Content
是一个字符串。当Event = comment
Content
是JSON对象时。
我想在需要之前推迟联合Content
。为此,我在我的结构中映射RawContent
并在Content()
上定义Message
方法以返回正确的对象。
以下是代码说明:
package main
import (
"fmt"
"encoding/json"
)
// Message represents a Flowdock chat message.
type Message struct {
Event *string `json:"event,omitempty"`
RawContent *json.RawMessage `json:"content,omitempty"`
}
func (m *Message) Content() (content interface{}) {
// when m.Event is a message the RawContent is a string
// real code handles unmarshaling other types (removed for this example)
return string(*m.RawContent)
}
func main() {
var message = &Message{}
rawJSON := `{"event": "message", "content": "Howdy-Doo @Jackie #awesome"}`
if err := json.Unmarshal([]byte(rawJSON), &message); err != nil {
panic(err.Error())
}
event := "message"
rawMessage := json.RawMessage("Howdy-Doo @Jackie #awesome")
want := &Message{
Event: &event,
RawContent: &rawMessage,
}
fmt.Println(message.Content(), want.Content())
}
运行此结果的结果是:http://play.golang.org/p/eds_AA6Aay
"Howdy-Doo @Jackie #awesome" Howdy-Doo @Jackie #awesome
注意:message.Content()和want.Content()是不同的!
起初我没想到引号会被包含在消息中,但是由于JSON的解析方式,它才有意义。它只是整个rawJSON
字符串的一部分。
所以我的问题是:
以下是一个更完整的示例,展示了我如何处理JSON RawContent
:http://play.golang.org/p/vrBJ5RYcql
答案 0 :(得分:3)
问题1:
不,你应该json.Unmarshal内容也只包含一个字符串。除了引号之外,JSON字符串还可能包含反斜杠转义的控制字符。
问题2:
由于问题1中的答案,请对“消息”案例执行以下操作:
var s string
if err := json.Unmarshal([]byte(*m.RawContent), &s); err != nil {
panic(err)
}
return s
问题3:
这是解组事件类型字符串并使用RawMessage
存储JSON其余部分的好方法,直到您评估了类型并知道内容具有何种结构。
您可能还想考虑具有特定类型的简单字符串内容,例如:
type MessageContent string
通过这种方式,您可以自由地在类型上实现方法,允许Content方法返回除空接口{}之外的其他接口。
注意:
请注意,如果您还按照我的建议对json.Unmarshal消息字符串进行解组,那么当您尝试解组未引用的want.RawContent字符串时,您的Playground示例会发生混乱,因为它不是有效的JSON。