go 45 lines · 5 steps

Custom JSON marshaling in Go

How implementing MarshalJSON lets you reshape Go structs into exactly the JSON you want.

Explained by highlit
1package model
2 
3import (
4 "encoding/json"
5 "strings"
6 "time"
7)
8 
9type Money int64
10 
11type Order struct {
12 ID string
13 Customer string
14 Total Money
15 Tags []string
16 CreatedAt time.Time
17 ShippedAt *time.Time
18}
19 
20func (m Money) MarshalJSON() ([]byte, error) {
21 dollars := float64(m) / 100
22 return json.Marshal(dollars)
23}
24 
25func (o Order) MarshalJSON() ([]byte, error) {
26 type alias struct {
27 ID string `json:"id"`
28 Customer string `json:"customer"`
29 Total Money `json:"total"`
30 Tags string `json:"tags"`
31 CreatedAt string `json:"created_at"`
32 Shipped bool `json:"shipped"`
33 ShippedAt *time.Time `json:"shipped_at,omitempty"`
34 }
35 
36 return json.Marshal(alias{
37 ID: o.ID,
38 Customer: o.Customer,
39 Total: o.Total,
40 Tags: strings.Join(o.Tags, ","),
41 CreatedAt: o.CreatedAt.UTC().Format(time.RFC3339),
42 Shipped: o.ShippedAt != nil,
43 ShippedAt: o.ShippedAt,
44 })
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing MarshalJSON on a named type customizes its JSON representation everywhere it appears.
  2. 2A local alias struct lets you reshape fields and tags without recursing into the original type's marshaler.
  3. 3Derived fields like a boolean flag or formatted timestamp can be computed at serialization time.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Custom JSON marshaling in Go — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code