JSON minify करें

JSON चिपकाइए और वही डेटा बिना एक भी फ़ालतू स्पेस के पाइए, साथ में यह भी कि इससे असल में कितना बचा — बाइट में, अक्षरों में नहीं, क्योंकि हिंदी सामग्री के साथ ये दो अलग संख्याएँ हैं। दस्तावेज़ parse होकर दोबारा लिखा जाता है, किसी ढूँढ़ो-और-बदलो से नहीं काटा जाता; इसीलिए किसी स्ट्रिंग के भीतर पड़े स्पेस बचे रहते हैं।

नतीजा

आप लिखते जाइए, जवाब यहाँ आता जाएगा।

  • कहाँ चलता है

    कुछ भी अपलोड नहीं होता, क्योंकि कोई फ़ाइल है ही नहीं — गणना इसी पन्ने में होती है।

  • न कतार, न खाता

    यह उतनी ही तेज़ी से जवाब देता है जितनी आपकी मशीन देती है, और कभी नहीं पूछता कि आप कौन हैं।

  • जितनी बार चाहें

    न कुछ गिना जाता है, न कोई सीमा है — दोबारा जवाब देने में हमारा कुछ ख़र्च नहीं होता।

काम कैसे करता है

  1. JSON चिपकाइए।
  2. तय कीजिए कि कुंजियाँ वर्णक्रम में लगानी हैं या नहीं — दो दस्तावेज़ों की तुलना करनी हो तो काम की चीज़।
  3. पंक्ति कॉपी कर लीजिए। कुछ अपलोड नहीं हुआ है।

यह parse होती है, काटी नहीं जाती

JSON छोटी करने का तेज़ तरीक़ा यह है कि सारे स्पेस और पंक्ति-विच्छेद हटा दिए जाएँ। वही ग़लत तरीक़ा भी है, क्योंकि किसी स्ट्रिंग के भीतर का स्पेस डेटा का हिस्सा है: `"पूरा नाम"` `"पूरानाम"` बन जाता है, और चूँकि नतीजा अब भी वैध JSON है, बहुत बाद तक किसी को पता नहीं चलता।

यहाँ दस्तावेज़ अंतर्निहित parser से पढ़ा जाता है और दोबारा लिखा जाता है। इसलिए जो बाहर आता है वह गारंटी के साथ वही डेटा-ढाँचा है: ऐसा कोई इनपुट है ही नहीं जिसके लिए छोटा करना सामग्री बदल दे, क्योंकि किसी भी क्षण टेक्स्ट को टेक्स्ट की तरह नहीं बरता जाता।

बचत बाइट में गिनी जाती है, अक्षरों में नहीं

यहाँ दिखाई गई बचत UTF-8 बाइट में है, जो वही संख्या है जो असल में गिनी जाती है: देवनागरी का हर अक्षर तीन बाइट लेता है, कोई emoji चार, कोई चीनी अक्षर तीन। हिंदी टेक्स्ट वाला दस्तावेज़ बाइट में अपने अक्षरों की गिनती से लगभग तीन गुना भारी होता है।

जो बचत को अक्षरों में मापता है उसे शुद्ध ASCII वाले payload पर लगभग वही संख्या मिलती है और हिंदी सामग्री वाले payload पर बिलकुल अलग। चूँकि यहाँ हमेशा किसी रास्ते या किसी भंडारण-फ़ील्ड की बात होती है, और दोनों बाइट गिनते हैं, गणना बाइट में की जाती है।

Gzip पहले से हो तो minify करने से क्या मिलता है

लगभग हर API दबाकर जवाब देती है, और Gzip दोहराए गए ख़ाली स्थान के ख़िलाफ़ असाधारण रूप से अच्छा है: किसी पंक्ति की शुरुआत में चार स्पेस, हज़ार बार, दबाने के बाद लगभग कुछ भी ख़र्च नहीं करते। इसलिए रास्ते पर होने वाली बचत यहाँ दिखने वाली संख्या से बहुत कम है, अक्सर एक अंक का प्रतिशत।

जहाँ यह सचमुच काम आता है वह जगह वही है जहाँ कुछ दबाया नहीं जाता: कोई पर्यावरण-वेरिएबल, लंबाई की सीमा वाला कोई डेटाबेस फ़ील्ड, कोई लॉग, आकार की सीमा वाला कोई क़तार-संदेश। वहाँ कच्ची बाइट की संख्या ही सीमा है, और वहाँ फ़र्क़ असली है।

Escape किया हुआ रूप बचत को उलट देता है

कुछ लाइब्रेरियाँ ASCII से बाहर के हर अक्षर को `\u0915` जैसे escape में लिखती हैं। वह छह ASCII बाइट है, जबकि वही अक्षर UTF-8 में तीन बाइट का होता। यानी escape किया हुआ हिंदी JSON अपने सामान्य रूप से ठीक दोगुना भारी होता है, और यह बढ़त पूरे दस्तावेज़ पर लगती है।

व्यावहारिक नतीजा यह है कि किसी सीमित फ़ील्ड में जगह बचाने के लिए सजावट हटाने से पहले यह देख लेना चाहिए कि serializer escape कर रहा है या नहीं। सजावट हटाकर शायद पाँच प्रतिशत बचे; escape बंद करके आधा। यह पन्ना escape को वापस नहीं बदलता — वह डेटा की प्रस्तुति नहीं, उसका रूप है, और उसका फ़ैसला बनाने वाले के पास है।

कुंजियाँ क्रम में लगाने से क्या मिलता है

JSON के object का कोई तय क्रम नहीं होता, इसलिए दो सेवाएँ वही डेटा अलग-अलग क्रम में लौटा सकती हैं। तब टेक्स्ट की तुलना वहाँ अंतर दिखाती है जहाँ अंतर है ही नहीं — यही आम वजह है कि कोई contract test लाल हो जाता है जबकि दोनों पक्ष एक ही बात कह रहे होते हैं।

दोनों दस्तावेज़ों को कुंजियाँ क्रम में लगाकर minify करने से ऐसा रूप बनता है जिसमें शाब्दिक तुलना सही जवाब देती है। यही तरीक़ा cache key और JSON पर बनाए गए हस्ताक्षरों के पीछे भी है: जिस चीज़ पर hash निकलता है उसे एक निश्चित रूप चाहिए, वरना hash serializer के मूड पर निर्भर हो जाता है।

क्रम में लगाना canonical बनाना नहीं है

हस्ताक्षरों के लिए एक असली विनिर्देश मौजूद है, RFC 8785, और वह क्रम से ज़्यादा तय करता है: संख्याएँ कैसे लिखी जाएँ, ख़ास अक्षर कैसे escape हों, और क्रम किस आधार पर लगे — UTF-16 इकाइयों के हिसाब से, न कि इस हिसाब से कि कोई भाषा किसे वर्णक्रम मानती है।

यह भेद हिंदी में और भी साफ़ दिखता है, क्योंकि देवनागरी का वर्णक्रम और UTF-16 इकाइयों का क्रम एक जैसे नहीं हैं। यहाँ का क्रम तुलना और diff के लिए व्यावहारिक रूप है, हस्ताक्षरों के लिए नियामक नहीं। Diff के लिए यह पर्याप्त से ज़्यादा है; जो JSON पर हस्ताक्षर करता है उसे विनिर्देश पढ़ना चाहिए।

लंबी पहचान-संख्याएँ यहाँ भी नहीं बचतीं

JSON संख्याओं को टेक्स्ट की तरह लिखती है और JavaScript उन्हें दोहरी परिशुद्धता के दशमलव की तरह पढ़ता है। 9,00,71,99,25,47,40,991 से बड़े पूर्णांक अंक खोने लगते हैं: 19 अंकों की कोई पहचान-संख्या बदली हुई निकलती है, और चूँकि नतीजा अब भी वैध संख्या जैसा दिखता है, किसी को पता नहीं चलता।

यह हर उस प्रक्रिया पर लागू है जो JavaScript के parser से गुज़रती है, इस पन्ने समेत। आम वजह snowflake क़िस्म की पहचान-संख्याएँ और कुछ डेटाबेस अनुक्रम होते हैं। हल उनके बनाने वाले के पास है: ऐसे मान स्ट्रिंग के रूप में जाने चाहिए, तब वे हर चरण से बिना बदले निकल जाते हैं।

एक पंक्ति किसी repository की चीज़ नहीं है

किसी version-नियंत्रित फ़ाइल के भीतर सिकुड़ी हुई JSON हर बदलाव को एक बदली हुई पंक्ति में बदल देती है। Diff सब-कुछ-या-कुछ-नहीं हो जाता, समीक्षा असंभव हो जाती है, और merge का टकराव उन दो फ़ील्ड के बजाय पूरे दस्तावेज़ को छूता है जिनकी बात थी।

जो बँटवारा चलता है वह यह है: repository में सजी हुई, परोसते समय सिकुड़ी हुई। Format वाला पन्ना वापसी का रास्ता है, और दोनों के बीच ठीक वह क़दम है जो किसी build प्रक्रिया को ख़ुद उठाना चाहिए।

आख़िर का पंक्ति-विच्छेद

यहाँ का नतीजा बिना पंक्ति-विच्छेद के ख़त्म होता है, क्योंकि वह एक पंक्ति है, कोई फ़ाइल नहीं। जो उसे किसी फ़ाइल में लिखे उसे एक जोड़ लेना चाहिए: POSIX टेक्स्ट की पंक्ति को ऐसी चीज़ मानता है जो पंक्ति-विच्छेद पर ख़त्म हो, और `cat` से लेकर Git तक के औज़ार बिना उसके फ़ाइलों के साथ अजीब बर्ताव करते हैं।

यह checksum मिलाते समय मायने रखने लगता है। आख़िरी पंक्ति-विच्छेद वाली फ़ाइल का hash उसके बिना वाली फ़ाइल के hash से पूरी तरह अलग होता है, भले दोनों में वही JSON हो — यह उन वजहों में से एक है कि दो मान जिन्हें मिलना चाहिए था नहीं मिलते।

संख्याओं की लिखावट बदल सकती है, उनका मान नहीं

दस्तावेज़ parse होकर दोबारा लिखा जाता है, इसलिए संख्याएँ उस रूप में निकलती हैं जिसमें JavaScript उन्हें लिखता है, ज़रूरी नहीं कि उसी रूप में जिसमें आपने उन्हें दिया था। `1.0` `1` बन जाता है, `1e2` `100` बन जाता है और `0.50` `0.5`। मान वही रहता है; लिखावट नहीं।

पढ़ने के लिए यह बेमानी है और हस्ताक्षरों के लिए नहीं। अगर कोई तंत्र JSON के ठीक-ठीक अक्षरों पर hash निकालता है, तो यह क़दम उस hash को बदल देता है, भले डेटा एक बाल भर न बदला हो। इसीलिए हस्ताक्षर हमेशा एक निश्चित रूप पर लगाए जाते हैं जो ख़ुद तय करता है कि संख्याएँ कैसे लिखी जाएँगी, न कि किसी serializer के मन पर छोड़े जाते हैं।

DPDP Act के लिहाज़ से इसका क्या मतलब है

किसी JSON payload में अक्सर ठीक वही होता है जिसे हिलाना नहीं चाहिए: ग्राहकों के रिकॉर्ड, ऑर्डर का डेटा, नाम-पते वाला कोई webhook, कभी-कभी Aadhaar या PAN जैसे खाने। चूँकि यहाँ parse और लेखन उसी पन्ने पर होता है, वह सामग्री हम तक नहीं पहुँचती और उस पर हमारी कोई प्रोसेसिंग की भूमिका नहीं बनती।

यह नेटवर्क पैनल में साबित होता है: इस्तेमाल के दौरान ऐसी कोई रिक्वेस्ट नहीं निकलती जो आपका दस्तावेज़ ले जाए। यही वजह है कि यह औज़ार वहाँ चल सकता है जहाँ सर्वर वाला रूप किसी आंतरिक नीति से टकरा जाता, और जाँचने में एक मिनट लगता है।

JSON minify करें: आम सवाल

क्या मेरी स्ट्रिंग के भीतर के स्पेस बचे रहते हैं?

हाँ। दस्तावेज़ parse होकर दोबारा लिखा जाता है, अक्षर-दर-अक्षर काटा नहीं जाता: किसी स्ट्रिंग के भीतर का स्पेस डेटा का हिस्सा है और उसे छुआ नहीं जाता। सिर्फ़ ढाँचे के तत्वों के बीच का ख़ाली स्थान जाता है।

अगर मेरी API पहले से Gzip इस्तेमाल करती है तो क्या यह फ़ायदेमंद है?

रास्ते पर बमुश्किल: Gzip दोहराए गए ख़ाली स्थान के ख़िलाफ़ बहुत अच्छा है। फ़ायदा वहाँ है जहाँ कुछ दबाया नहीं जाता — पर्यावरण-वेरिएबल, लंबाई की सीमा वाले फ़ील्ड, आकार की सीमा वाले क़तार-संदेश।

मेरी लंबी पहचान-संख्या क्यों बदल जाती है?

क्योंकि JavaScript संख्याओं को दोहरी परिशुद्धता के दशमलव की तरह पढ़ता है और 9,00,71,99,25,47,40,991 से बड़े पूर्णांक अंक खो देते हैं। ऐसी पहचान-संख्याओं को JSON में स्ट्रिंग के रूप में चलना चाहिए।

टिप्पणियों वाला मेरा दस्तावेज़ मना क्यों किया जाता है?

क्योंकि JSON में टिप्पणियाँ होती ही नहीं, न आख़िरी अल्पविराम, न बिना उद्धरण वाली कुंजियाँ। अगर कॉन्फ़िग में टिप्पणियाँ चाहिए तो उपयुक्त फ़ॉर्मैट YAML, TOML या JSON5 है।

क्या JSON मेरे डिवाइस से बाहर जाती है?

नहीं। वह इसी पन्ने पर parse और लिखी जाती है। जाँचने का तरीक़ा नेटवर्क पैनल है: इस्तेमाल के दौरान ऐसी कोई रिक्वेस्ट नहीं निकलती जो आपका दस्तावेज़ ले जाए।

और टूल्स