Given the following structs:
type Person {
Name string `json:\"name\"`
}
type Employee {
Person
JobRole string `json:\"jobRole\"`
}
<
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))
}