如何在编组时省略结构字段**,但在解组时保留它?

KOG*_*OGI 5 json marshalling go unmarshalling

我有一个带有密码字段的User结构.当我通过POSTed JSON创建用户(或使用新密码更新)时,我想接受/解密密码字段到我的对象,但每当我返回用户时,我想省略密码字段.以下是迄今为止我能够提出的最好的.它可以工作,但它需要大量重复我想要消除的字段名称(现在,如果我添加一个新的字段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)
}
Run Code Online (Sandbox Code Playgroud)

在Go Playground 尝试一下

Sch*_*ern 5

利用嵌入式结构.定义用户,并将其嵌入到添加密码字段(以及其他任何内容,如付款信息)的UnsafeUser中.

type User struct {
    Id       string `json:"id"`
    Username string `json:"username"`
}

type UnsafeUser struct {
    User
    Password string `json:"pwd"`
}
Run Code Online (Sandbox Code Playgroud)

(最好是默认情况下安全,并声明什么是不安全的,比如Go的不安全的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"}
Run Code Online (Sandbox Code Playgroud)

请注意如何在Unmarshalled UnsafeUser中看到嵌入的User结构.


klv*_*gai 5

我有同样的问题,但遇到了这篇文章。

这个想法是使用嵌入和匿名结构来覆盖字段。

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)
}
Run Code Online (Sandbox Code Playgroud)

尝试一下

别名有助于在编组时防止无限循环。

请注意,您必须保持相同的 JSON 字段名称才能覆盖工作。