Home >Backend Development >Golang >How to Idiomatically Embed a Struct with a Custom `MarshalJSON()` in Go?
The challenge arises when an embedded struct defines a customized MarshalJSON() method, causing unexpected JSON serialization behavior when attempting to marshal the containing struct.
Consider the following struct definitions:
type Person struct { Name string `json:"name"` } type Employee struct { *Person JobRole string `json:"jobRole"` }
Marshaling the Employee struct as expected is straightforward:
p := Person{"Bob"} e := Employee{&p, "Sales"} output, _ := json.Marshal(e) fmt.Printf("%s\n", string(output))
Output:
{"name":"Bob","jobRole":"Sales"}
However, defining a custom MarshalJSON() method for the embedded struct, as shown below, disrupts the intended serialization:
func (p *Person) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ Name string `json:"name"` }{ Name: strings.ToUpper(p.Name), }) }
Now, marshaling the Employee produces output with the name field converted to uppercase but misses the jobRole field:
{"name":"BOB"}
To maintain the desired serialization behavior, avoid defining a MarshalJSON() method on the embedded struct (Person). Instead, create a separate type encapsulating the custom marshalling logic and embed that type:
type Name string func (n Name) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ Name string `json:"name"` }{ Name: strings.ToUpper(string(n)), }) } type Person struct { Name Name `json:"name"` }
This approach isolates the marshalling customization to a dedicated type, preventing unexpected side effects when embedding the Person struct elsewhere.
Example: https://play.golang.org/p/u96T4C6PaY
The above is the detailed content of How to Idiomatically Embed a Struct with a Custom `MarshalJSON()` in Go?. For more information, please follow other related articles on the PHP Chinese website!