2025, Nov 01 13:31

ट्रिपल‑क्वोटेड स्ट्रिंग्स भूलें: Python requests में JSON सीरियलाइज़ करें

जानें क्यों ट्रिपल‑क्वोटेड स्ट्रिंग से JSON पेलोड बनाना टूटता है, और Python requests में dict, json.dumps या json= से सुरक्षित व वैध पेलोड भेजें. आसानी से.

Python की requests लाइब्रेरी के लिए JSON पेलोड बनाते समय जब आप ट्रिपल‑क्वोटेड स्ट्रिंग में सीधे variables डालने की कोशिश करते हैं, तो यह पहली नजर में सुविधाजनक लगता है। लेकिन व्यवहार में यह नाज़ुक होता है, ज़रा‑सा बदलाव होते ही टूट जाता है, और जैसे ही स्ट्रक्चर बदलता है या मानों में ऐसे अक्षर आते हैं जिन्हें एस्केप करना पड़ता है, सब गड़बड़ हो जाता है। आम स्थिति: आप CSV पर इटरेट करते हुए MAC और NAME को डायनेमिक रखना चाहते हैं। सही तरीका है डेटा को Python ऑब्जेक्ट्स के रूप में बनाना और उन्हें serialize करना—बिना JSON को हाथ से फॉर्मैट किए।

समस्या का उदाहरण

यह पैटर्न अक्सर परेशानी बनता है, जब variables को JSON बॉडी में बदलने की कोशिश की जाती है:

payload = '''{
    "clients": [
        {
            "mac": HW_MAC,
            "name": HOST_ALIAS
        },
    ],}'''

यह 'देखने में' JSON जैसा लगता है, लेकिन यह वैध JSON नहीं है, और placeholders को variables की तरह नहीं पढ़ा जाएगा। ऊपर से, आख़िरी तत्व के बाद लगी कॉमा (trailing comma) और गलत ब्रेसेज़ पार्सिंग तोड़ देंगे।

असल में गड़बड़ होती कहाँ है

JSON को हाथ से फॉर्मैट करना गलतियों से भरा होता है। आख़िरी तत्व के बाद लगी कॉमा मान्य नहीं होती और parse errors देती है। अगर आप f‑string से variables डालने की कोशिश करते हैं, तो कर्ली ब्रैसेज़ को दोगुना लिखना पड़ता है, वरना वे फ़ॉर्मैट मार्कर समझे जाते हैं। सबसे अहम बात, string interpolation आपके लिए जरूरी escaping नहीं करती; उद्धरण चिह्न या विशेष वर्ण वाले मान अमान्य आउटपुट बना देंगे। Serializer यह सब सही और एकसमान तरीके से संभालता है।

समाधान: Python ऑब्जेक्ट बनाइए और json.dumps से serialize कीजिए

सीधा‑सादा Python dict या list बनाइए, फिर json.dumps की मदद से उसे JSON स्ट्रिंग में बदलिए। यह तरीका इटरेशन के दौरान आपके डेटा टाइप्स को जस‑का‑तस रखता है, और serializer वैध JSON तथा सही escaping की गारंटी देता है।

import json
HW_MAC = 'xxxxxxxxxxxx'
HOST_ALIAS = 'example'
request_body = json.dumps({
  "clients": [
    {"mac": HW_MAC, "name": HOST_ALIAS}
  ]
}, indent=2)
print(request_body)

आउटपुट:

{
  "clients": [
    {
      "mac": "xxxxxxxxxxxx",
      "name": "example"
    }
  ]
}

CSV की हर पंक्ति पर चलते हुए HW_MAC और HOST_ALIAS जैसे variables को मौजूदा मान सौंपिए, dict दोबारा बनाइए, और फिर से serialize कीजिए। बस इतना ही—ना नाज़ुक string concatenation, ना ही मैनुअल quoting।

क्या आपको सच में JSON स्ट्रिंग चाहिए?

HTTP method और endpoint पर निर्भर करते हुए, अक्सर आपको खुद से कुछ भी stringify करने की ज़रूरत नहीं होती। उदाहरण के लिए, GET में params के ज़रिए query पैरामीटर्स भेजे जा सकते हैं, और PUT में data के ज़रिए form‑encoded डेटा। दोनों ही स्थितियों में encoding को requests संभाल लेता है।

import requests
query_args = {"key1": "value1", "key2": "value2"}
resp = requests.get("https://httpbin.org/get", params=query_args)
import requests
resp = requests.put("https://httpbin.org/put", data={"key": "value"})

आप json= आर्ग्युमेंट के साथ Python dict भी दे सकते हैं—requests उसे अपने आप JSON में serialize कर देगा और Content-Type हेडर सेट कर देगा।

import requests
resp = requests.get("https://httpbin.org/get", json={"some": "data"})

यह क्यों मायने रखता है

Serializer को JSON बनाने देने से एक पूरी श्रेणी की बारीक बग्स खत्म हो जाती हैं। यह तय करता है कि स्ट्रक्चर सही रहे, trailing commas अंदर न घुस आएँ, और स्ट्रिंग्स के भीतर सभी ज़रूरी अक्षर ठीक से escaped हों। नतीजा: साफ‑सुथरा कोड, जिसे पेलोड बदलने पर बनाए रखना आसान होता है।

निष्कर्ष

requests के लिए JSON स्ट्रिंग्स हाथ से बनाना बंद करें। जब सच में JSON स्ट्रिंग चाहिए, तो native Python स्ट्रक्चर्स और json.dumps का उपयोग करें; वरना ज़रूरत के मुताबिक params, data या json के साथ डेटा सीधे पास करें। इससे आपके पेलोड वैध रहते हैं, मंशा स्पष्ट रहती है, और MAC तथा NAME जैसे डायनेमिक मानों पर इटरेट करते समय कोड मज़बूत बना रहता है।

यह लेख StackOverflow के एक प्रश्न (लेखक: Joseph Jenkins) और Mark Tolonen के उत्तर पर आधारित है।