Marshalled struct to json

时间:2018-06-04 08:11:33

标签: json go

我有以下结构:

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!"}

我怎样才能做到这一点?

1 个答案:

答案 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