Custom marshaling allows you to control how your types are converted to and from JSON. By implementing the MarshalJSON method on a type, you can customize the JSON representation. This is particularly useful for types like time.Time that have a natural JSON representation different from their Go structure.
The MarshalJSON method receives a receiver and returns a JSON-encoded byte slice and an error. Inside the method, you have complete control over what gets marshalled. A common pattern is to create an alias type to avoid infinite recursion, embed it in a temporary struct with custom fields, and marshal that temporary struct.
Similarly, the UnmarshalJSON method allows you to parse custom JSON formats into your types. This enables bidirectional custom serialization, making it possible to handle complex or legacy JSON formats that don’t map cleanly to Go structs.