Home >Backend Development >Golang >How to Embed Structs with Custom `MarshalJSON()` Methods Idiomatically in Go?

How to Embed Structs with Custom `MarshalJSON()` Methods Idiomatically in Go?

Susan Sarandon
Susan SarandonOriginal
2024-12-13 18:45:11458browse

How to Embed Structs with Custom `MarshalJSON()` Methods Idiomatically in Go?

Idiomatic Way to Embed Struct with Custom MarshalJSON() Method

Given the structs below, we can easily marshal an Employee struct to JSON as expected:

type Person struct {
    Name string `json:"name"`
}

type Employee struct {
    *Person
    JobRole string `json:"jobRole"`
}

However, when the embedded struct has a custom MarshalJSON() method, it breaks the marshalling process:

func (p *Person) MarshalJSON() ([]byte, error) {
    return json.Marshal(struct {
        Name string `json:"name"`
    }{
        Name: strings.ToUpper(p.Name),
    })
}

This is because the embedded Person struct implements the MarshalJSON() function, which takes precedence over the Employee struct's own MarshalJSON() method.

The desired output is to encode the Employee fields normally, while deferring to the Person's MarshalJSON() method to marshal its fields. However, adding a MarshalJSON() method to Employee requires knowing that the embedded type implements MarshalJSON() as well, which can be fragile.

To resolve this issue, we can use a different approach:

  1. Create a new type Name to represent the Person's name:

    type Name string
  2. Implement MarshalJSON() on Name to customize its encoding:

    func (n Name) MarshalJSON() ([]byte, error) {
     return json.Marshal(strings.ToUpper(string(n)))
    }
  3. Modify the Person struct to use Name instead of string:

    type Person struct {
     Name Name `json:"name"`
    }

This approach allows us to customize the encoding of the Person's name without requiring a MarshalJSON() method on the Employee struct.

Alternatively, if we want to implement this more generically, we need to implement MarshalJSON on the outer type. Methods on the inner type are promoted to the outer type, so we can call the inner type's MarshalJSON method, unmarshal its output into a generic structure like map[string]interface{}, and add our own fields. However, this can have the side effect of changing the order of the final output fields.

The above is the detailed content of How to Embed Structs with Custom `MarshalJSON()` Methods Idiomatically in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn