Home >Backend Development >Golang >How to Correctly MarshalJSON() for Embedded Structs with Custom Marshaling?

How to Correctly MarshalJSON() for Embedded Structs with Custom Marshaling?

Linda Hamilton
Linda HamiltonOriginal
2024-12-07 10:40:16836browse

How to Correctly MarshalJSON() for Embedded Structs with Custom Marshaling?

Idiomatic Way to Embed Struct with Custom MarshalJSON() Method

Problem:

How can we encode a struct with an embedded struct that has a custom MarshalJSON() method? The expected output is to preserve the custom marshaling of the embedded struct while also encoding the fields of the outer struct.

Example:

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

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

When the embedded Person struct has a custom MarshalJSON() method:

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

Marshaling an Employee instance breaks, resulting in:

{"name": "BOB"}

Solution:

Instead of implementing MarshalJSON() on Person, create a new Name type that implements MarshalJSON(). Then, modify Person to use this Name 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 allows the custom marshaling logic to be applied to the Name field while still encoding the Employee fields as expected.

Generic Solution:

For a more generic solution, implement MarshalJSON() on the outer struct. While methods on the inner type are promoted to the outer type, the outer type can then unmarshal the result into a generic structure like map[string]interface{} and add its own fields.

Example:

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

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

func (e *Employee) MarshalJSON() ([]byte, error) {
    b, err := e.Person.MarshalJSON()
    if err != nil {
        return nil, err
    }

    var m map[string]interface{}
    if err := json.Unmarshal(b, &m); err != nil {
        return nil, err
    }

    m["jobRole"] = e.JobRole
    return json.Marshal(m)
}

The above is the detailed content of How to Correctly MarshalJSON() for Embedded Structs with Custom Marshaling?. 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