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 User
v := struct {
Alias
Age 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 User
v := struct {
Alias
Age int `json:"age"`
}{
Alias: Alias(u), Age: 18,
}
return json.Marshal(v)
}
type UserPermissions struct {
User
Permissions []string `json:"permissions"`
}
func (u UserPermissions) MarshalJSON() ([]byte, error) {
type Alias UserPermissions
v := 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 User
v := struct {
Alias
Age int `json:"age"`
}{
Alias: Alias(u),
Age: 18,
}
return json.Marshal(v)
}
type UserPermissions struct {
User
Permissions []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>
}