2013-10-09 9 views
8

काल्पनिक (एक और struct में struct embedding), मैं एक API चलाने के लिए और जब कोई उपयोगकर्ता उपयोगकर्ता संसाधन पर GET अनुरोध करता है, मैं एक JSONGolang + MongoDB एम्बेडेड प्रकार

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

के रूप में प्रासंगिक क्षेत्रों वापस आ जाएगी जैसा कि आप देख सकते हैं, उपयोगकर्ता में गुप्त क्षेत्र में json:"-" है। इसका तात्पर्य है कि अधिकांश ऑपरेशन में मैं वापस नहीं लौटना चाहूंगा। इस मामले में, एक प्रतिक्रिया होगी

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

क्षेत्र गुप्त json:"-" के रूप में लौटाया नहीं जाएगा क्षेत्र अस्वीकार करते हैं।

अब, मैं केवल एक व्यवस्थापक खोल रहा हूं जहां मैं गुप्त क्षेत्र वापस करना चाहता हूं। हालांकि, इसका मतलब उपयोगकर्ता संरचना को डुप्लिकेट करना होगा।

मेरे वर्तमान समाधान इस तरह दिखता है:

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

वहाँ adminUser में उपयोगकर्ता एम्बेड करने के लिए एक तरीका है? की तरह विरासत का प्रकार:

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

ऊपर वर्तमान में केवल क्षेत्र रहस्य के रूप में काम नहीं करता, इस मामले में लौटा दी जाएगी।

नोट: वास्तविक कोड बेस में, कुछ दर्जन फ़ील्ड हैं। इस प्रकार, डुप्लिकेटिंग कोड की लागत अधिक है।

वास्तविक मोंगो क्वेरी नीचे है:

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

उत्तर

22

आप bson पैकेज के इनलाइन झंडा पर एक नज़र (कि bson.Marshal के तहत दर्ज है) लेना चाहिए। अब आपको लगता है कि आप नकली चाबी त्रुटियों पाने पर ध्यान देंगे जब आप दोनों adminUser और User के बाद से इस संरचना, साथ डेटाबेस से पढ़ने का प्रयास करते हैं,

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

हालांकि: यह आप इस तरह कुछ करने के लिए अनुमति चाहिए कुंजी secret शामिल है।

आपके मामले में मैं User से Secret क्षेत्र को दूर हूं और मैं केवल adminUser में से एक है। फिर जब भी आपको secret फ़ील्ड पर लिखना होगा, सुनिश्चित करें कि आप adminUser का उपयोग करते हैं।

+0

इस मामले में, मुझे रनटाइम त्रुटि मिल रही है: आंतरिक सर्वर त्रुटि संरचना main.adminUser में डुप्लिकेट कुंजी 'गुप्त'! – samol

+0

मेरा जवाब अपडेट किया गया। मुझे एहसास नहीं हुआ कि डुप्लिकेट कुंजी शामिल थीं। –

+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. 
... 

संपादित करें: एक अंतरफलक यहाँ उपयोग करने का कारण मामलों में जहां आप तार एक आम तरीका का उपयोग करने पर मनमाने ढंग से मॉडल भेज सकते हैं के लिए है।