18

仮説として、私は API を実行し、ユーザーがユーザー リソースに対して GET リクエストを行うと、関連するフィールドを 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"`
}

ご覧のとおり、 User の Secret フィールドにはjson:"-". これは、ほとんどの操作で戻りたくないことを意味します。この場合、レスポンスは次のようになります。

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

json:"-"はフィールドを省略しているため、フィールド secret は返されません。

今、秘密のフィールドを返したい管理者専用ルートを開いています。ただし、それは User 構造体を複製することを意味します。

私の現在のソリューションは次のようになります。

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"`
}

User を adminUser に埋め込む方法はありますか? 継承のようなもの:

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

この場合、フィールドのシークレットのみが返されるため、上記は現在機能しません。

注: 実際のコード ベースには、数十のフィールドがあります。そのため、コードを複製するコストは高くなります。

実際の mongo クエリは次のとおりです。

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)
}
4

2 に答える 2

56

bson パッケージのインライン フラグを確認する必要があります ( bson.Marshalに記載されています)。次のようなことができるはずです。

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

adminUserただし、 と の両方にUserkey が含まれているため、この構造でデータベースから読み取ろうとすると、重複キー エラーが発生することがわかりますsecret

あなたの場合、私はSecretからフィールドを削除し、User にあるものだけを持っていadminUserます。secret次に、フィールドに書き込む必要があるときはいつでも、 adminUser.

于 2013-10-09T18:35:18.850 に答える
1

もう 1 つの方法は、インターフェイスを宣言することです。

type SecureModel interface {
    SecureMe()
}

モデルがそれを実装していることを確認してください。

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 = ""
}

そして、どのルートが呼び出されるかに応じてのみ呼び出します。

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

編集: ここでインターフェイスを使用する理由は、一般的な方法を使用してネットワーク上で任意のモデルを送信する可能性がある場合です。

于 2013-12-18T07:08:37.910 に答える