我有以下结构:
type Message struct {
DoubleMe int `json:"double_me"`
Message string `json:"message"`
}
它的一个例子:
m := Message{5, "Hello, World!"}
我的目标是在DoubleMe
字段封送到json时执行某些操作,例如将其加倍。所以输出将是:
{"double_me":10,"message":"Hello, World!"}
我怎样才能做到这一点?
答案 0 :(得分:3)
在你的struct上实现json.Marshaler
,这是为了定义一个自定义编组逻辑,它可以使DoubleMe
字段加倍。
见这个例子:
type Message struct {
DoubleMe int `json:"double_me"`
Message string `json:"message"`
}
func (m Message) MarshalJSON() ([]byte, error) {
m.DoubleMe *= 2
type Message2 Message
return json.Marshal(Message2(m))
}
func main() {
m := Message{5, "Hello, World!"}
data, err := json.Marshal(m)
fmt.Println(string(data), err)
fmt.Println("Original:", m)
}
输出(在Go Playground上尝试):
{"double_me":10,"message":"Hello, World!"} <nil>
Original: {5 Hello, World!}
一些注意事项:
如果你需要这个也可以向后工作(例如,在解组时,将值除以2),还要实现json.Unmarshaler
(留给读者作为练习)。
即使我们将场地翻倍,在编组之后,原始值也没有改变。这是因为该方法具有非指针接收器,因此在该方法内仅获取并修改了副本,而不是原始值。如果我们使用指针接收器,我们将不得不负责恢复它。
另请注意,在Message2
方法中创建并使用了新类型MarshalJSON()
。这是因为我们还使用json
包来执行&#34;通常&#34;一旦我们应用了我们的自定义逻辑,就会编组。但是,如果我们将m
传递给json.Marshal()
,那将是无休止的#34;递归&#34;,因为json
包会再次调用此MarshalJSON()
方法。相反,我们创建了一个Message2
类型,其Message
作为其基础类型。这意味着Message2
没有方法(它没有实现json.Marshaler
),因此将值Message2
传递给json.Marshal()
将不会再次调用此方法,因为它具有{ {1}}作为其基础类型,我们只需将Message
类型的值转换为Message
。