Go में JSON का जादू: क्यों कुछ फ़ील्ड दिखते हैं और कुछ नहीं?
\nक्या आपने कभी ऐसी स्थिति का सामना किया है जब आपकी Go स्ट्रक्चर JSON प्रतिक्रिया में वह भेज रही हो जो क्लाइंट को देखना बिल्कुल ज़रूरी नहीं है? उदाहरण के लिए, उपयोगकर्ता का पासवर्ड, आंतरिक डेटाबेस ID या गुप्त कुंजी। या, इसके विपरीत, किसी फ़ील्ड को केवल एक निश्चित शर्त पर दिखाने की आवश्यकता हो (जैसे, यदि वह खाली नहीं है)।
\nयह समस्या Stack Overflow पर सबसे लोकप्रिय में से एक है, और यह व्यर्थ नहीं है। Go में JSON के साथ काम करना प्रकारों की कठोरता और प्रस्तुति के लचीलेपन के बीच संतुलन की कला है। आज हम सभी तरीकों पर चर्चा करेंगे: सरल टैग json:"-" से लेकर इंटरफ़ेस के साथ जटिल कस्टम समाधानों तक। चलिए शुरू करते हैं!
1. सबसे आसान तरीका: टैग json:"-"
\nGo आपको विशेष टैग के माध्यम से स्ट्रक्चर के सीरियलाइज़ेशन को नियंत्रित करने की अनुमति देता है। यदि आप किसी फ़ील्ड को JSON से हमेशा के लिए छुपाना चाहते हैं, तो बस json:"-" जोड़ें।
type User struct {\n Name string `json:"name"`\n Password string `json:"-"`\n Age int `json:"age"`\n}\n\nfunc main() {\n u := User{Name: "आलिसा", Password: "supersecret", Age: 30}\n data, _ := json.Marshal(u)\n fmt.Println(string(data))\n // आउटपुट: {"name":"आलिसा","age":30}\n}\nPassword फ़ील्ड गायब हो गया, जैसे कि वह कभी था ही नहीं। संवेदनशील डेटा के लिए आदर्श जो कभी भी सर्वर से बाहर नहीं जाना चाहिए।
2. सशर्त छुपाना: omitempty
\nकभी-कभी किसी फ़ील्ड को केवल तभी छुपाने की आवश्यकता होती है जब वह खाली हो। इसके लिए omitempty विकल्प का उपयोग किया जाता है ("omit if empty" का संक्षिप्त रूप)।
type Product struct {\n Name string `json:"name"`\n Description string `json:"description,omitempty"`\n Price float64 `json:"price,omitempty"`\n}\n\nfunc main() {\n p1 := Product{Name: "किताब", Price: 500.0}\n data1, _ := json.Marshal(p1)\n fmt.Println(string(data1)) // {"name":"किताब","price":500}\n\n p2 := Product{Name: "कोर्स"}\n data2, _ := json.Marshal(p2)\n fmt.Println(string(data2)) // {"name":"कोर्स"}\n}\nमहत्वपूर्ण: omitempty केवल "शून्य" मानों के साथ काम करता है: "", 0, false, nil (स्लाइस, मैप, पॉइंटर्स के लिए)।
संख्यात्मक फ़ील्ड के साथ जाल
\nसावधान रहें: यदि Price 0 के बराबर है, तो वह भी छिप जाएगा। कुछ व्यावसायिक तर्कों में यह अस्वीकार्य है (मुफ़्त उत्पाद भी एक मूल्य है)। ऐसे मामलों में पॉइंटर्स का उपयोग करना बेहतर है।
3. पॉइंटर्स (*) और इंटरफ़ेस का उपयोग
\nपॉइंटर्स आपके सबसे अच्छे दोस्त हैं जब आपको "मान निर्दिष्ट नहीं" और "मान शून्य के बराबर" के बीच अंतर करने की आवश्यकता होती है।
\ntype UserProfile struct {\n Name string `json:"name"`\n Age *int `json:"age,omitempty"` // int पर पॉइंटर\n Bio *string `json:"bio,omitempty"`\n}\n\nfunc main() {\n // आयु निर्दिष्ट नहीं — फ़ील्ड छिप जाएगा\n u1 := UserProfile{Name: "इवान"}\n data1, _ := json.Marshal(u1)\n fmt.Println(string(data1)) // {"name":"इवान"}\n\n // आयु = 0 — यह एक सार्थक मान है\n zero := 0\n u2 := UserProfile{Name: "मारिया", Age: &zero}\n data2, _ := json.Marshal(u2)\n fmt.Println(string(data2)) // {"name":"मारिया","age":0}\n}\nइस दृष्टिकोण का उपयोग अक्सर REST API में किया जाता है, जहाँ केवल पास किए गए फ़ील्ड को अपडेट करने की आवश्यकता होती है (आंशिक अपडेट, PATCH अनुरोध)।
\n\n4. कस्टम सीरियलाइज़ेशन: इंटरफ़ेस json.Marshaler
\nयदि मानक टैग पर्याप्त नहीं हैं, तो आप प्रक्रिया को पूरी तरह से नियंत्रित कर सकते हैं। json.Marshaler इंटरफ़ेस को लागू करें और अपना स्वयं का तर्क लिखें।
type DynamicUser struct {\n ID int\n Name string\n ShowEmail bool\n Email string\n}\n\nfunc (u DynamicUser) MarshalJSON() ([]byte, error) {\n // केवल सीरियलाइज़ेशन के लिए एक अनाम स्ट्रक्चर बनाएँ\n m := map[string]interface{}{\n "id": u.ID,\n "name": u.Name,\n }\n if u.ShowEmail {