0 day streak
go / intermediate
Snippet

Implementing Custom JSON Marshaling for Domain Types

By implementing json.Marshaler and json.Unmarshaler on custom types, you control how Go structs convert to and from JSON. This is particularly useful for representing enums as readable strings in JSON API payloads rather than raw integer values.

snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package main
import (
"encoding/json"
"fmt"
"strings"
)
type Status int
const (
Pending Status = iota
Active
)
func (s Status) MarshalJSON() ([]byte, error) {
var str string
switch s {
case Pending:
str = "pending"
case Active:
str = "active"
default:
str = "unknown"
}
return json.Marshal(str)
}
func (s *Status) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
caseInsensitive := strings.ToLower(str)
switch caseInsensitive {
case "pending":
*s = Pending
case "active":
*s = Active
default:
return fmt.Errorf("invalid status: %s", str)
}
return nil
}
Breakdown
1
func (s Status) MarshalJSON() ([]byte, error) {
Implements the json.Marshaler interface to convert the custom integer status type into a human-readable JSON string.
2
func (s *Status) UnmarshalJSON(data []byte) error {
Implements the json.Unmarshaler interface. It uses a pointer receiver to modify the target value during JSON decoding.
3
*s = Pending
Dereferences the receiver pointer to update the status based on the parsed JSON string value.