Интерфейс json.Marshaler

Интерфейс json.Marshaler предоставляет механизм для кастомной маршализации JSON. Он содержит метод MarshalJSON, который возвращает байтовый срез JSON-данных и ошибку. Реализуя этот интерфейс для пользовательского типа, мы можем определить собственный формат представления данных в JSON, отличный от стандартного.

Синтаксис

gotype Marshaler interface {
  MarshalJSON() ([]byte, error)
}

Пример

Рассмотрим структуру, представляющую пользователя. Стандартная маршализация выведет все поля в JSON. Мы хотим изменить формат вывода, скрыв некоторые поля:

gopackage main

import (
  "encoding/json"
  "fmt"
  "log"
)

type User struct {
  Name   string
  Password string
  Age    int
}

// Реализация MarshalJSON
func (u User) MarshalJSON() ([]byte, error) {
  return json.Marshal(struct {
    Name string `json:"name"`
    Age  int  `json:"age"`
  }{
    Name: u.Name,
    Age:  u.Age,
  })
}

func main() {
  user := User{
    Name:   "alice",
    Password: "secret123",
    Age:    30,
  }

  res, err := json.Marshal(user)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(string(res))
}

Результат выполнения кода:

go{"name":"alice","age":30}

Как видим, поле Password не попало в финальный JSON, а имена полей были приведены к нижнему регистру.

Пример

Теперь реализуем маршализацию для типа данных с нестандартным форматом. Создадим тип Duration, который будет выводиться в JSON как строка в формате "Xh Ym Zs":

gopackage main

import (
  "encoding/json"
  "fmt"
  "log"
  "time"
)

type Duration struct {
  Seconds int
}

func (d Duration) MarshalJSON() ([]byte, error) {
  hours := d.Seconds / 3600
  minutes := (d.Seconds % 3600) / 60
  seconds := d.Seconds % 60

  var s string
  if hours > 0 {
    s += fmt.Sprintf("%dh ", hours)
  }
  if minutes > 0 || hours > 0 {
    s += fmt.Sprintf("%dm ", minutes)
  }
  s += fmt.Sprintf("%ds", seconds)

  return []byte(fmt.Sprintf("%q", s)), nil
}

type Task struct {
  Title  string   `json:"title"`
  Duration Duration `json:"duration"`
}

func main() {
  task := Task{
    Title:  "Complete project",
    Duration: Duration{Seconds: 3665},
  }

  res, err := json.Marshal(task)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(string(res))
}

Результат выполнения кода:

go{"title":"Complete project","duration":"1h 1m 5s"}

Пример

Интерфейс json.Marshaler также позволяет изменять структуру данных на основе условий или преобразов

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить