golang-忽略json属性而不被序列化的优雅方法

yst*_*ark 3 json go

我有一个用户结构,其中包含诸如密码之类的敏感字段:

type User struct {
    UID string `json:"uid"  binding:"required"`
    Password string `json:"password" binding:"required"`
    EmailAddress string `json:"email" binding:"required"`
}
Run Code Online (Sandbox Code Playgroud)

现在,我希望能够使用此结构来注册用户并进行更新,删除以及查看。我不希望将密码序列化以供查看。我当然可以制作一个自定义编组,但这是唯一的方法吗?我尝试使用该json:"-"选项,但是这也会在取消编组时将其忽略,这是我不希望的。有没有更好的办法?

编辑: 为了让你们中的一些人放心,我当然不会以明文形式存储密码。它是密码的bcrypt哈希,但仍然如此。搜索用户时,我不希望它返回。

R3v*_*v4n 8

我会选择另一个结构和组合。

密码永远不应该以纯文本形式存储,它们应该被安全地散列(bcrypt、pbkdf2 等)。该散列是必须存储且永远不应序列化的散列。通过使用组合,您可以执行以下操作:

type User struct {
    UID string `json:"uid"  binding:"required"`
    HashedPassword string `json:"-"`
    EmailAddress string `json:"email" binding:"required"`
}

type UserFormData struct {
   User
   Password string `json:"password" binding:"required"`
}
Run Code Online (Sandbox Code Playgroud)

这也为您提供了更大的灵活性。例如,如果您要求用户确认密码,您可以简单地更改 UserFormData 结构,如下所示:

type UserFormData struct {
   User
   Password string `json:"password" binding:"required"`
   ConfirmPassword string `json:"confirm_password" binding:"required"`
}
Run Code Online (Sandbox Code Playgroud)

它还具有将序列化细节保留在 User 对象之外的优势。


Sir*_*ius 5

一个简单的解决方案是在编组之前清理用户结构:

type User struct {
    UID          string `json:"uid"  binding:"required"`
    Password     string `json:"password,omitempty" binding:"required"`
    EmailAddress string `json:"email" binding:"required"`
}

func sanitizeUser(u User) User {
    return User{u.UID, "", u.EmailAddress}
}
Run Code Online (Sandbox Code Playgroud)

演示:https : //play.golang.org/p/RjKVoFc9o8


Pet*_*ter 5

我想说实现json.Marshaler是一个优雅的解决方案,如果您想自定义封送处理。在这种情况下非常简单:

func (u User) MarshalJSON() ([]byte, error) {
    type user User // prevent recursion
    x := user(u)
    x.Password = ""
    return json.Marshal(x)
}
Run Code Online (Sandbox Code Playgroud)

如果在编组时根本不需要密码字段,请在用户类型中添加“ omitempty”。