如何在编组时*仅*省略结构字段,但在解组时保留它?
How do I omit a struct field *only* when marshalling, but keep it when unmarshalling?
我有一个带有密码字段的用户结构。当我通过 POSTed JSON 创建用户(或使用新密码更新)时,我想 accept/unmarshal 将密码字段添加到我的对象中,但每当我 return一个用户,我想省略密码字段。以下是迄今为止我能想到的最好的。它有效,但它需要围绕我想消除的字段名称重复 lot(现在,如果我添加一个新字段,如 FirstName
,我有在 3 个不同的地方添加它)。
如何更好地做到这一点同时仍然尊重结构上的json
标签?
func main() {
origJson := []byte(`{"id":"1","username":"Chad","pwd":"sillypants"}`)
fmt.Println("Original: " + string(origJson))
var unmarshalled User
json.Unmarshal(origJson, &unmarshalled)
fmt.Printf("Unmarshalled: %+v\n", unmarshalled)
marshalled, _ := json.Marshal(unmarshalled)
fmt.Println("ReMarshalled: " + string(marshalled))
}
type User struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"pwd"`
}
type SafeUser struct {
Id string `json:"id"`
Username string `json:"username"`
}
func (u User) MarshalJSON() ([]byte, error) {
safeUser := SafeUser{
Id : u.Id,
Username: u.Username,
}
return json.Marshal(safeUser)
}
Try it 在 Go Playground
利用embedded structs。定义一个用户,并将其嵌入到添加密码字段(以及其他任何内容,如支付信息)的 UnsafeUser 中。
type User struct {
Id string `json:"id"`
Username string `json:"username"`
}
type UnsafeUser struct {
User
Password string `json:"pwd"`
}
(最好让事情默认安全并声明不安全的事情,比如Go's unsafe pacakge。)
然后您可以从 UnsafeUser 中提取用户,而无需知道并复制所有字段。
func (uu UnsafeUser) MarshalJSON() ([]byte, error) {
return json.Marshal(uu.User)
}
$ go run ~/tmp/test.go
Original: {"id":"1","username":"Chad","pwd":"sillypants"}
Unmarshalled: {User:{Id:1 Username:Chad} Password:sillypants}
ReMarshalled: {"id":"1","username":"Chad"}
请注意如何查看嵌入在未编组的 UnsafeUser 中的用户结构。
我遇到了同样的问题,但遇到了 this article。
想法是使用嵌入和匿名结构来覆盖字段。
func (u User) MarshalJSON() ([]byte, error) {
type Alias User
safeUser := struct {
Password string `json:"pwd,omitempty"`
Alias
}{
// Leave out the password so that it is empty
Alias: Alias(u),
}
return json.Marshal(safeUser)
}
别名有助于防止编组时出现无限循环。
请注意,您必须保持相同的 JSON 字段名称才能使覆盖生效。
我有一个带有密码字段的用户结构。当我通过 POSTed JSON 创建用户(或使用新密码更新)时,我想 accept/unmarshal 将密码字段添加到我的对象中,但每当我 return一个用户,我想省略密码字段。以下是迄今为止我能想到的最好的。它有效,但它需要围绕我想消除的字段名称重复 lot(现在,如果我添加一个新字段,如 FirstName
,我有在 3 个不同的地方添加它)。
如何更好地做到这一点同时仍然尊重结构上的json
标签?
func main() {
origJson := []byte(`{"id":"1","username":"Chad","pwd":"sillypants"}`)
fmt.Println("Original: " + string(origJson))
var unmarshalled User
json.Unmarshal(origJson, &unmarshalled)
fmt.Printf("Unmarshalled: %+v\n", unmarshalled)
marshalled, _ := json.Marshal(unmarshalled)
fmt.Println("ReMarshalled: " + string(marshalled))
}
type User struct {
Id string `json:"id"`
Username string `json:"username"`
Password string `json:"pwd"`
}
type SafeUser struct {
Id string `json:"id"`
Username string `json:"username"`
}
func (u User) MarshalJSON() ([]byte, error) {
safeUser := SafeUser{
Id : u.Id,
Username: u.Username,
}
return json.Marshal(safeUser)
}
Try it 在 Go Playground
利用embedded structs。定义一个用户,并将其嵌入到添加密码字段(以及其他任何内容,如支付信息)的 UnsafeUser 中。
type User struct {
Id string `json:"id"`
Username string `json:"username"`
}
type UnsafeUser struct {
User
Password string `json:"pwd"`
}
(最好让事情默认安全并声明不安全的事情,比如Go's unsafe pacakge。)
然后您可以从 UnsafeUser 中提取用户,而无需知道并复制所有字段。
func (uu UnsafeUser) MarshalJSON() ([]byte, error) {
return json.Marshal(uu.User)
}
$ go run ~/tmp/test.go
Original: {"id":"1","username":"Chad","pwd":"sillypants"}
Unmarshalled: {User:{Id:1 Username:Chad} Password:sillypants}
ReMarshalled: {"id":"1","username":"Chad"}
请注意如何查看嵌入在未编组的 UnsafeUser 中的用户结构。
我遇到了同样的问题,但遇到了 this article。
想法是使用嵌入和匿名结构来覆盖字段。
func (u User) MarshalJSON() ([]byte, error) {
type Alias User
safeUser := struct {
Password string `json:"pwd,omitempty"`
Alias
}{
// Leave out the password so that it is empty
Alias: Alias(u),
}
return json.Marshal(safeUser)
}
别名有助于防止编组时出现无限循环。
请注意,您必须保持相同的 JSON 字段名称才能使覆盖生效。