Built-in type Golang + MongoDB (nesting a structure in another structure)

Hypothetical, I run the API and when the user makes a GET request on the user's resource, I will return the corresponding fields as JSON

type User struct { Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` Name string `json:"name,omitempty" bson:"name,omitempty"` Secret string `json:"-,omitempty" bson:"secret,omitempty"` } 

As you can see, the "Secret" field in "User" has json:"-" . This means that in most operations I would not want to return. In this case, the answer will be

 { "id":1, "Name": "John" } 

The field secret is not returned because json:"-" omits the field.

Now I open the route only for the administrator, where I would like to return the secret field. However, this would mean duplication of the user structure.

My current solution looks like this:

 type adminUser struct { Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` Name string `json:"name,omitempty" bson:"name,omitempty"` Secret string `json:"secret,omitempty" bson:"secret,omitempty"` } 

Is there any way to insert user into adminUser? Kind of like inheritance:

 type adminUser struct { User Secret string `json:"secret,omitempty" bson:"secret,omitempty"` } 

This does not currently work, as in this case only the secret secret will be returned.

Note. In a real code base there are several dozen fields. Thus, the cost of duplicating code is high.

The actual mango request is below:

 func getUser(w http.ResponseWriter, r *http.Request) { ....omitted code... var user adminUser err := common.GetDB(r).C("users").Find( bson.M{"_id": userId}, ).One(&user) if err != nil { return } common.ServeJSON(w, &user) } 
+8
mongodb go
source share
2 answers

You should take a look at the bson package built-in flag (this is described in bson.Marshal ). This should allow you to do something like this:

 type adminUser struct { User `bson:",inline"` Secret string `json:"secret,omitempty" bson:"secret,omitempty"` } 

However, now you will notice that you get duplicates of key errors when you try to read from a database with this structure, since adminUser and User contain the secret key.

In your case, I will remove the secret field from User and has only one of adminUser . Then, when you need to write in the secret field, make sure that you are using adminUser .

+22
source share

Another alternative would be to declare an interface.

 type SecureModel interface { SecureMe() } 

Make sure your model implements it:

 type User struct { Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"` Username string `json:"username" bson:"username"` Secret string `json:"secret,omitempty" bson:"secret"` } func (u *User) SecureMe() { u.Secret = "" } 

And is called only depending on which route is called.

 // I am being sent to a non-admin, secure me. if _, ok := user.(SecureModel); ok { user.(SecureModel).SecureMe() } // Marshall to JSON, etc. ... 

Edit: The reason for using the interface here is when you can send arbitrary models by wire using a common method.

+1
source share

All Articles