परिचय: क्यों हर Java डेवलपर को यह ट्रिक जाननी चाहिए
\n\nकल्पना करें: आपको सर्वर से JSON मिला, उसमें दर्जनों समान प्रकार के ऑब्जेक्ट हैं। ग्राहक, उत्पाद, लॉग — कोई फर्क नहीं पड़ता। आप ObjectMapper लेते हैं, readValue(json, MyClass[].class) लिखते हैं — और सब काम करता है। लेकिन एक महीने बाद कोड ClassCastException के साथ क्रैश हो जाता है, क्योंकि किसी ने ऐरे को List से बदल दिया। परिचित लगता है?
Stack Overflow पर «How to use Jackson to deserialise an array of objects» प्रश्न ने दसियों हज़ार व्यूज़ एकत्र किए हैं। और यह कोई संयोग नहीं है: जावा में ऑब्जेक्ट्स की ऐरे को डिसीरियलाइज़ करना उन कार्यों में से एक है जो तब तक सरल लगते हैं जब तक आप जेनेरिक्स और Type Erasure का सामना नहीं करते। 2025 में, Jackson JSON के साथ काम करने के लिए डी-फैक्टो मानक बना हुआ है, लेकिन सर्वोत्तम प्रथाएँ बदल गई हैं। इस लेख में, हम न केवल बुनियादी दृष्टिकोणों को, बल्कि आधुनिक तकनीकों को भी समझेंगे जो आपको सिरदर्द से बचाएंगी।
\n\nबुनियादी दृष्टिकोण: ऐरे या सूची?
\n\nसबसे सरल तरीका ऐरे का उपयोग करना है। Jackson अच्छी तरह समझता है कि MyClass[].class ऑब्जेक्ट्स की एक ऐरे है:
ObjectMapper mapper = new ObjectMapper();\nString json = "[{\\"id\\":1,\\"name\\":\\"Alice\\"},{\\"id\\":2,\\"name\\":\\"Bob\\"}]";\nMyClass[] array = mapper.readValue(json, MyClass[].class);\n\nकाम करता है? हाँ। लेकिन इस दृष्टिकोण की कमियाँ हैं:
\n- \n
- ऐरे का आकार निश्चित होता है — गतिशील डेटा के लिए असुविधाजनक। \n
- कलेक्शन विधियाँ (
stream(),filter(),remove()) उपलब्ध नहीं हैं। \n - यदि बाद में
Listकी आवश्यकता हो तो विस्तार करना कठिन है। \n
इसलिए 90% मामलों में, आप List<MyClass> प्राप्त करना चाहेंगे। और यहाँ सबसे दिलचस्प शुरू होता है — जावा में Type Erasure। यदि आप लिखते हैं:
List<MyClass> list = mapper.readValue(json, List.class); // warning: unchecked\n\nकंपाइलर चेतावनी देगा, और रनटाइम पर आपको List<LinkedHashMap> मिलेगा, न कि List<MyClass>। जेनेरिक्स मिट जाते हैं, और Jackson को पता नहीं चलता कि एलिमेंट्स को किसमें मैप करना है।
TypeReference: List के लिए सही तरीका
\n\nसमाधान TypeReference का उपयोग करना है। यह एक अनाम आंतरिक वर्ग है जो रिफ्लेक्शन के माध्यम से जेनेरिक्स के बारे में जानकारी संरक्षित करता है:
List<MyClass> list = mapper.readValue(json, new TypeReference<List<MyClass>>() {});\n\n{} पर ध्यान दें — यह एक अनाम वर्ग बनाता है जो प्रकार को कैप्चर करता है। Jackson TypeFactory के माध्यम से समझता है कि MyClass की List को डिसीरियलाइज़ करना है। यह दृष्टिकोण 2025 में स्वर्ण मानक है।
TypeReference कब असुविधाजनक है?
\n- \n
- यदि आप गतिशील रूप से प्रकार बनाते हैं (जैसे, कॉन्फ़िगरेशन से)। \n
- यदि एक ही चीज़ को बार-बार डिसीरियलाइज़ करना हो — हर बार अनाम वर्ग बनाना महँगा हो सकता है। \n
इन मामलों के लिए एक विकल्प है — CollectionType।
\n\nCollectionType: JavaType की शक्ति
\n\nJackson जटिल प्रकार बनाने के लिए TypeFactory प्रदान करता है:
JavaType type = mapper.getTypeFactory()\n .constructCollectionType(List.class, MyClass.class);\nList<MyClass> list = mapper.readValue(json, type);\n\nयह विधि:
\n- \n
- अनाम वर्ग नहीं बनाती (कम ओवरहेड)। \n
- गतिशील रूप से प्रकार बनाने की अनुमति देती है:
constructParametricType(Map.class, String.class, MyClass.class)। \n - लाइब्रेरी और फ्रेमवर्क के लिए आदर्श है जहाँ प्रकार कंपाइल टाइम पर ज्ञात नहीं होते। \n
2025 की सर्वोत्तम प्रथा: सरल मामलों के लिए TypeReference का उपयोग करें, और जब लचीलापन या प्रदर्शन की आवश्यकता हो तो CollectionType का उपयोग करें।
Reader और InputStream: संसाधनों को न भूलें
\n\n
ब्लॉग
पुस्तक अनुशंसाएँ
यह भी पढ़ें