1

I have a User struct containing sensitive fields like password and email. For a public instance of User, for example a public RSVP on an event page, I want to exclude sensitive fields from appearing in my JSON output, even if they're blank.

Based on this article, I’m using a composite struct to mask undesired fields.

QUESTION: during rows.Scan in my database func, how do I properly access the fields of the pointer struct within the composite struct? I’m getting panic errors thrown, because fields are not being found.

My regular User struct:

type User struct {
    ID          int `json:"id"`
    FirstName   string `json:"firstname"`
    LastName    string `json:"lastname"`
    Registered  int `json:"registered"`
    Email       string `json:"email"`
    Password    string `json:"password"`
    ProfilePic  string `json:"profilepic"`
}

The new additional structs based on the method in the article linked above:

type omit *struct {

}


type PublicUser struct {
    *User
    Registered omit `json:”registered,omitempty"`
    Email omit `json:”email,omitempty"`
    Password omit `json:"password,omitempty"`
}

My database func, where an error is occuring:

func getUsers(db *sql.DB) ([]PublicUser, error) {

    query := `SELECT users.id, users.name_first, users.name_last
    FROM users
    ORDER BY users.name_first asc`

    users := []PublicUser{}

    rows, err := db.Query(query, e.ID)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    for rows.Next() {

        var user PublicUser


        // ERROR OCCURS HERE. Seems like these fields cannot be found in PublicUser.
        // Is the pointer to User working within my PublicUser struct?

        err := rows.Scan(&user.ID, &user.FirstName, &user.LastName)



        if err != nil {
            return nil, err
        }

        users = append(users, user)
    }

    return users, nil

}

My original JSON output, not using the articles' method; only using my regular User struct:

[{

    "ID": 25,
    "FirstName": "Jim",
    "LastName": "Brown",
    "Registered": 0,
    "Email": "",
    "Password": "",
    "ProfilePic": ""

},
…
]

Desired JSON output:

[{

    "ID": 25,
    "FirstName": "Jim",
    "LastName": "Brown",
    "ProfilePic": ""

},
…
]
Kalnode
  • 9,386
  • 3
  • 34
  • 62
  • what about json Marshal option omit? https://stackoverflow.com/questions/17306358/removing-fields-from-struct-or-hiding-them-in-json-response – bigless Sep 17 '17 at 14:28
  • Have you tried `Password string \`json:"-"\`` and the same for `Username`? – Eugene Lisitsky Sep 17 '17 at 14:48
  • https://play.golang.org/p/10MKQXmEyV – Eugene Lisitsky Sep 17 '17 at 14:55
  • Eugene: Thx for the suggestion, however this means excluding those fields for all other uses of User. For example, on the user's profile page, I would need to display the Email field (using the regular User struct). – Kalnode Sep 17 '17 at 16:35

1 Answers1

3

Problem there is that when you initialize the variable here:

var user PublicUser

All the fields for user take their "zero" values.

Since you are embedding a pointer, and zero value for pointers is nil, you can't use that pointer without getting an error.

In order for this to work, you should initialize user like this:

user = PublicUser{ User: &User{} }

(or don't declare it as a pointer)

See a playground here showing the issue and then initializing the variable as described above for it to work.

https://play.golang.org/p/fXwvATUm_L

eugenioy
  • 11,825
  • 28
  • 35
  • Thanks, this works! What I see now is that the excluded fields still exist in the JSON output (although empty). I suppose I'll have to process the JSON and remove empty fields before sending it out. – Kalnode Sep 17 '17 at 21:36
  • 1
    ... or just simply forget all this composite struct business and just make a totally new, seperate struct just for public instances of the user. Which right now seems a lot better. – Kalnode Sep 17 '17 at 21:41