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
Release: 2024-12-07 10:40:16
Original
807 people have browsed it

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"`
}
Copy after login

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),
    })
}
Copy after login

Marshaling an Employee instance breaks, resulting in:

{"name": "BOB"}
Copy after login

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"`
}
Copy after login

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)
}
Copy after login

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template