Выполните операцию на поле, когда Marshalled struct to json - PullRequest
0 голосов
/ 04 июня 2018

У меня есть следующая структура:

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 голосов
/ 04 июня 2018

Реализуйте 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 для выполнения «обычного» маршалинга после того, как применили нашу собственную логику.Но если мы передадим m в json.Marshal(), это будет бесконечная «рекурсия», потому что пакет json снова вызовет этот метод MarshalJSON().Вместо этого мы создали тип Message2 с базовым типом Message.Это означает, что Message2 имеет нулевые методы (он не реализует json.Marshaler), поэтому передача значения Message2 в json.Marshal() больше не будет вызывать этот метод, и, поскольку он имеет Message в качестве базового типа, мыможно просто преобразовать значение типа Message в Message2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...