How do I omit a struct field *only* when marshalling, but keep it when unmarshalling?

Viewed 925

I have a User struct with a password field. When I'm creating a user (or udpating with a new password) via POSTed JSON, I want to accept/unmarshal the password field into my object, but whenever I return a user, I want to omit the password field. Below is the best I've been able to come up with so far. It works, but it requires a lot of duplication around the field names that I'd like to eliminate (right now, if I add a new field like FirstName, I have to add that in 3 separate places).

How do I do this better while still honoring the json tags on the struct?

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 on the Go Playground

2 Answers
Related