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
}