我正在使用Echo框架和Gorm在Go中编写Web服务。
我有一个User
结构,如下所示:
type User struct {
ID uint `json:"user_id"`
Email string `json:"email_address,omitempty" validate:"required,email"`
}
我接受POST
次请求Content-type: application/json
。
我希望我的输入为{"email_address": "email@email.com"}
,输出为{"user_id": 1}
如何禁止用户在请求中提交ID
(因此他们无法创建包含某些ID
的记录),但请在响应中保留ID
?
现在我在保存之前正在做user.ID = 0
,但我想知道是否有更好的方法可以做到这一点?
我还想在输出中跳过Email
。现在我在输出之前做user.Email = ""
。还有更好的方法吗?
谢谢!
答案 0 :(得分:1)
我通过使它更通用来扩展你的例子,并且我展示了更普遍问题的优雅解决方案。
我们假设在User
中有:
你的例子是"子集"这个(在你的例子中没有共同的字段)。
无需使用embedding重复字段即可优雅地解决此问题。您可以创建3种不同的类型;一个用于公共字段UserBoth
,一个用于仅输入字段UserIn
,另一个用于仅输出字段UserOut
:
type UserBoth struct {
Name string `json:"name"`
Age int `json:"age"`
}
type UserIn struct {
*UserBoth
Email string `json:"email"`
}
type UserOut struct {
*UserBoth
ID uint `json:"id"`
}
请注意UserBoth
(或更确切地说*UserBoth
以避免重复结构值)嵌入UserIn
和UserOut
中,因为我们希望这两个字段都存在。< / p>
现在,如果您的输入包含所有字段(即使我们不想要所有字段):
const in = `{"name":"Bob","age":23,"Email":"as@as.com","id":123}`
解组为UserIn
的值只会解析您想要的内容:
uin := UserIn{UserBoth: &UserBoth{}}
err := json.Unmarshal([]byte(in), &uin)
fmt.Printf("%+v %+v %v\n", uin, uin.UserBoth, err)
输出(请注意Email
字段已解析,但ID
不是
{UserBoth:0x1050e150 Email:as@as.com} &{Name:Bob Age:23} <nil>
当您想要生成输出时:
uout := UserOut{UserBoth: uin.UserBoth}
// Fetch / set ID from db:
uout.ID = 456
out, err := json.Marshal(uout)
fmt.Println(string(out), err)
输出(请注意,ID
字段已存在,但Email
不是
{"name":"Bob","age":23,"id":456} <nil>
在Go Playground上尝试。
User
上面的示例使用了2个不同的结构:UserIn
用于解析,UserOut
用于生成输出。
如果在您的代码中,您想使用&#34;统一&#34; User
结构,这就是它的完成方式:
type User struct {
UserIn
UserOut
}
使用它:
uboth := &UserBoth{}
u := User{UserIn{UserBoth: uboth}, UserOut{UserBoth: uboth}}
err := json.Unmarshal([]byte(in), &u.UserIn)
fmt.Printf("%+v %+v %v\n", u, u.UserIn.UserBoth, err)
// Fetch / set ID from db:
u.ID = 456
out, err := json.Marshal(u.UserOut)
fmt.Println(string(out), err)
在Go Playground上试试这个。
答案 1 :(得分:0)
虽然icza的答案提出了一个很好的解决方案,但您也可以使用JSON编组辅助方法MarshalJSON/UnmarshalJSON
:
func main() {
// employing auxiliary json methods MarshalJSON/UnmarshalJSON
user := User{ID: 123, Email: `abc@xyz.com`}
js, _ := json.Marshal(&user)
log.Printf("%s", js)
input := UserInput(user)
js, _ = json.Marshal(&input)
log.Printf("%s", js)
output := UserOutput(user)
js, _ = json.Marshal(&output)
log.Printf("%s", js)
}
type User struct {
ID uint `json:"user_id"`
Email string `json:"email_address,omitempty" validate:"required,email"`
}
type UserInput User
func (x *UserInput) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Email string `json:"email_address,omitempty" validate:"required,email"`
}{
Email: x.Email,
})
}
type UserOutput User
func (x *UserOutput) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
ID uint `json:"user_id"`
}{
ID: x.ID,
})
}
这给了我们:
[ info ] main.go:25: {"user_id":123,"email_address":"abc@xyz.com"}
[ info ] main.go:29: {"email_address":"abc@xyz.com"}
[ info ] main.go:33: {"user_id":123}