Idiomatic way to embed struct with custom MarshalJSON() method

前端 未结 5 696
星月不相逢
星月不相逢 2021-02-04 09:30

Given the following structs:

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

type Employee {
    Person
    JobRole string `json:\"jobRole\"`
}
<
5条回答
  •  忘掉有多难
    2021-02-04 09:57

    A more generic way to support massive fields in both inner and outer fields.

    The side effect is you need to write this for every outer structs.

    Example: https://play.golang.org/p/iexkUYFJV9K

    package main
    
    import (
        "encoding/json"
        "fmt"
        "log"
        "strings"
    )
    
    func Struct2Json2Map(obj interface{}) (map[string]interface{}, error) {
        data, err := json.Marshal(obj)
        if err != nil {
            return nil, err
        }
        var kvs map[string]interface{}
        err = json.Unmarshal(data, &kvs)
        if err != nil {
            return nil, err
        }
        return kvs, nil
    }
    
    type Person struct {
        Name string `json:"-"`
    }
    
    func (p Person) MarshalJSONHelper() (map[string]interface{}, error) {
        return Struct2Json2Map(struct {
            Name string `json:"name"`
        }{
            Name: strings.ToUpper(p.Name),
        })
    
    }
    
    type Employee struct {
        Person
        JobRole string `json:"jobRole"`
    }
    
    func (e Employee) MarshalJSON() ([]byte, error) {
        personKvs, err := e.Person.MarshalJSONHelper()
        if err != nil {
            return nil, err
        }
    
        type AliasEmployee Employee
        kvs, err := Struct2Json2Map(struct {
            AliasEmployee
        } {
            AliasEmployee(e),
        })
    
        for k,v := range personKvs {
            kvs[k] = v
        }
        return json.Marshal(kvs)
    }
    
    func main() {
        bob := Employee{
            Person: Person{
                Name: "Bob",
            },
            JobRole: "Sales",
        }
    
        output, err := json.Marshal(bob)
        if err != nil {
            log.Fatal(err)
        }
    
        fmt.Println(string(output))
    }
    

提交回复
热议问题