How to Use Custom JSON Marshaling and Unmarshaling in Go

Implement MarshalJSON and UnmarshalJSON methods on your type to override default JSON encoding and decoding behavior in Go.

Custom JSON marshaling and unmarshaling in Go are achieved by implementing the MarshalJSON and UnmarshalJSON methods on a type, which override the default behavior of encoding/json. When json.Marshal is called, it checks for MarshalJSON on the type; if present, it executes that method instead of reflecting over fields. Similarly, json.Unmarshal calls UnmarshalJSON if the target type implements it, allowing you to define exactly how data is parsed.

package main

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

type MyTime struct {
	time.Time
}

func (m MyTime) MarshalJSON() ([]byte, error) {
	// Custom format: "2023-10-27"
	return []byte(`"` + m.Time.Format("2006-01-02") + `"`), nil
}

func (m *MyTime) UnmarshalJSON(data []byte) error {
	// Remove quotes
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	// Parse custom format
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return err
	}
	m.Time = t
	return nil
}

func main() {
	t := MyTime{time.Now()}
	b, _ := json.Marshal(t)
	fmt.Println(string(b)) // Output: "2023-10-27"

	var t2 MyTime
	json.Unmarshal([]byte(`"2023-10-27"`), &t2)
	fmt.Println(t2.Time) // Output: 2023-10-27 00:00:00 +0000 UTC
}