json
修改结构内某一属性
直接修改结构的值会引发无穷递归导致 panic:
type User struct {Name string `json:"name"`}func (u User) MarshalJSON() ([]byte, error) {u.Name = "li"return json.Marshal(u) // panic}func TestPanic(t *testing.T) {res,err:= json.Marshal(User{Name: "wang"})fmt.Println(string(res), err)}
🌈 通过重命名一个 Alias 解决:
type User struct {Name string `json:"name"`Gender string `json:"gender"`Role []string `json:"roles"`}func (u User) MarshalJSON() ([]byte, error) {type Alias Userv := struct {AliasAge int `json:"age"`}{Alias: Alias(u),Age: 18,}if v.Role == nil {v.Role = []string{}}return json.Marshal(v)}func TestAlias(t *testing.T) {res, err := json.Marshal(User{Name: "wang", Gender: "man"})fmt.Println(string(res), err)// {"name":"wang","gender":"man","roles":[],"age":18} <nil>}
匿名字段重写MarshalJSON,顶层结构的MarshalJSON失效
常规 Alias 会导致最终调用匿名字段的 MarshalJSON:
type User struct {Name string `json:"name"`}func (u User) MarshalJSON() ([]byte, error) {type Alias Userv := struct {AliasAge int `json:"age"`}{Alias: Alias(u), Age: 18,}return json.Marshal(v)}type UserPermissions struct {UserPermissions []string `json:"permissions"`}func (u UserPermissions) MarshalJSON() ([]byte, error) {type Alias UserPermissionsv := struct {Alias}{Alias: Alias(u)}return json.Marshal(v)}func TestUserPermissions(t *testing.T) {res, err := json.Marshal(UserPermissions{User: User{Name: "wang"}, Permissions: []string{"one", "two"}})fmt.Println(string(res), err)// {"name":"wang","age":18} <nil>}
🌈 通过一个中间map来解决:
感谢:
Struct含有匿名字段,该匿名字段有MarshalJSON方法,导致Struct不能正确转换成json字符串!!
Idiomatic way to embed struct with custom MarshalJSON() method
type User struct {Name string `json:"name"`}func (u User) MarshalJSON() ([]byte, error) {type Alias Userv := struct {AliasAge int `json:"age"`}{Alias: Alias(u),Age: 18,}return json.Marshal(v)}type UserPermissions struct {UserPermissions []string `json:"permissions"`}func (u UserPermissions) MarshalJSON() ([]byte, error) {pJSON, err := u.User.MarshalJSON()if err != nil {return nil, err}eJSON, err := json.Marshal(map[string]interface{}{"permissions": u.Permissions,})if err != nil {return nil, err}eJSON[0] = ','return append(pJSON[:len(pJSON)-1], eJSON...), nil}func TestUserPermissions(t *testing.T) {res, err := json.Marshal(UserPermissions{User: User{Name: "wang"}, Permissions: []string{"one", "two"}})fmt.Println(string(res), err)// {"name":"wang","age":18,"permissions":["one","two"]} <nil>}
