JSON ↔ YAML और XML रूपांतरण की सीमाएँ
मुख्य बात: यह दावा कि JSON, YAML का सबसेट है, केवल एक दिशा की गारंटी देता है, और XML का कोई आधिकारिक JSON मैपिंग ही नहीं है — सब कुछ परंपरा पर टिका है।

सार: JSON को मध्यवर्ती प्रारूप बनाएँ: स्रोत को डेटा मॉडल में पार्स करें, फिर लक्ष्य में serialize करें; रूपांतरण से पहले तय करें कि टिप्पणियाँ, XML attribute और namespace, तथा संख्या या boolean प्रकार बचने चाहिए या नहीं।
कोई रूपांतरण पाइपलाइन काम की है या नहीं, यह इस पर नहीं टिका कि आउटपुट कितना सुंदर दिखता है, बल्कि इस पर कि आप जानते हैं उसने कितना फेंक दिया।
1. JSON और YAML: एक-तरफ़ा समावेश
YAML 1.2 विनिर्देश स्पष्ट कहता है: JSON, YAML का सबसेट है। यानी कोई भी वैध JSON वैध YAML है:
{"name": "json", "tags": ["a", "b"], "count": 3}
यह टुकड़ा JSON और YAML flow शैली दोनों है। उल्टा सत्य नहीं है।
| विशेषता | JSON | YAML 1.2 |
|---|---|---|
| टिप्पणियाँ | ✗ | ✓ |
| Anchor और alias | ✗ | ✓ |
कई दस्तावेज़ (---) |
✗ | ✓ |
| गैर-स्ट्रिंग key | ✗ | ✓ (1: a, true: b) |
| जटिल key | ✗ | ✓ (? [a, b]) |
| इंडेंटेशन के प्रति संवेदनशील | ✗ | ✓ (tab इंडेंटेशन अस्वीकृत) |
| प्रकार अनुमान | स्पष्ट | अंतर्निहित (0o17, 0x1F, .inf) |
| एक-पंक्ति पठनीयता | अच्छी | खराब (लंबी सामग्री folding सिंटैक्स पर टिकती है) |
1.1 प्रकार अनुमान सबसे बड़ा जाल है
YAML कुछ ऐसे मान जो स्ट्रिंग जैसे दिखते हैं, अन्य प्रकारों में पार्स कर देता है:
zip: 01234 # string or octal integer? the YAML 1.2 core schema treats it as a string
version: 1.10 # 1.1 (a float); the semantics are lost
country: NO # a string in YAML 1.2; boolean false in YAML 1.1
date: 2026-10-30 # some implementations parse it as a date object
NO वाला उदाहरण बहुत लोगों को जला चुका है: YAML 1.1 parser (कुछ पुरानी लाइब्रेरी) के साथ country: NO false बन जाता है।
उपाय: हर ऐसे पहचानकर्ता को उद्धरण में रखें जो "संख्या या boolean जैसा दिखता है", जैसे version: "1.10"।
1.2 Anchor, alias और कई दस्तावेज़
defaults: &defaults
retries: 3
timeout: 30
serviceA:
<<: *defaults
host: a.example.com
---
serviceB:
<<: *defaults
host: b.example.com
Anchor खोलकर JSON में बदलने के बाद आमतौर पर या तो दो दोहराए हुए कॉन्फ़िगरेशन object मिलते हैं, या एक array (कई दस्तावेज़ों को [{...}, {...}] बनना ही होगा)।
किसी भी तरह, उल्टे रूपांतरण पर anchor बहाल नहीं होते — वह हानि अपरिहार्य है।
1.3 टिप्पणियाँ बचाने वाला रूपांतरण
अधिकांश लाइब्रेरी रूपांतरण के दौरान टिप्पणियाँ बस गिरा देती हैं। जब उन्हें रखना हो, तो yaml पैकेज का Document API इस्तेमाल करें:
import { parseDocument } from 'yaml';
const document = parseDocument(`
# Service configuration
port: 8080
`);
document.set('port', 3000);
console.log(document.toString());
// # Service configuration
// port: 3000
जाँच सरल है: यदि इस फ़ाइल को मनुष्य बार-बार संपादित करेंगे, तो "पार्स → object → serialize" का रास्ता न लें।
1.4 Round-trip संगति कैसे सत्यापित करें
/**
* Verifies round-trip consistency for JSON → YAML → JSON.
* @param sourceValue Original JSON value
* @param stringify YAML serialization function
* @param parse YAML parsing function
* @returns Whether the two results are exactly equal
*/
function isRoundTripStable(
sourceValue: unknown,
stringify: (input: unknown) => string,
parse: (input: string) => unknown,
): boolean {
const yamlText = stringify(sourceValue);
const restored = parse(yamlText);
return JSON.stringify(restored) === JSON.stringify(sourceValue);
}
इसे वास्तविक डेटा पर चलाना दस्तावेज़ दस बार पढ़ने से अधिक मूल्यवान है। सुनिश्चित करें कि आपका नमूना समुच्चय कवर करे: null, खाली स्ट्रिंग, खाली array, "00", "1e5", ऋणात्मक शून्य, 2^53 से बड़े पूर्णांक, और newline वाली लंबी स्ट्रिंग।
2. JSON और XML: कोई मानक मैपिंग नहीं है
XML, JSON से बहुत पहले का है और संरचनात्मक क्षमताएँ (attribute, namespace, mixed content, DTD) कहीं अधिक मज़बूत हैं। दोनों के बीच कोई आधिकारिक मैपिंग विनिर्देश नहीं है; हर टूल एक ही काम करता है: एक परंपरा चुनो, फिर ज़्यादा न खोने की कोशिश करो।
2.1 सामान्य परंपराएँ
| परंपरा | निरूपण | उदाहरण |
|---|---|---|
| Element → object key | समान नाम का element फ़ील्ड बन जाता है | <a>1</a> → {"a": "1"} |
Attribute → @ उपसर्ग |
@name |
<a id="1"/> → {"a": {"@id": "1"}} |
Text → #text |
जब attribute और text दोनों हों | <a id="1">hi</a> → {"a": {"@id": "1", "#text": "hi"}} |
| दोहराया element → array | दो या अधिक बार आने पर array बनता है | <i>1</i><i>2</i> → {"i": ["1","2"]} |
| Namespace → उपसर्ग | ns:tag |
<ns:tag/> → {"ns:tag": ...} |
<order id="A1001">
<item sku="X1" qty="2">笔记本</item>
<item sku="X2" qty="1">钢笔</item>
</order>
{
"order": {
"@id": "A1001",
"item": [
{ "@sku": "X1", "@qty": "2", "#text": "笔记本" },
{ "@sku": "X2", "@qty": "1", "#text": "钢笔" }
]
}
}
2.2 पाँच अपरिहार्य हानियाँ
- Element का क्रम: JSON object क्रम-रहित हैं, जबकि XML element का क्रमबद्ध अनुक्रम है;
- Attribute बनाम बाल element: XML में उनके अर्थ अलग हैं, पर JSON में दोनों सादे फ़ील्ड बन जाते हैं;
- Mixed content:
<p>你好 <b>世界</b> 再见</p>जैसी संरचनाएँ सादे object से व्यक्त नहीं हो सकतीं; - Namespace घोषणाएँ:
xmlnsएक scope की धारणा है; फ़ील्ड में flatten होते ही scope खो जाता है; - CDATA और entity:
<![CDATA[...]]>और&JSON में बस पाठ से ज़्यादा कुछ नहीं।
2.3 "एक element या array" की दुविधा
<list><item>1</item></list>
एक अकेले item के साथ xml2js डिफ़ॉल्ट रूप से object लौटाता है और array तभी लौटाता है जब दो हों।
नतीजा यह है कि फ़्रंटएंड कोड को Array.isArray(x) ? x : [x] लिखना पड़ता है।
उपाय: पार्स करते समय "always array" विकल्प चालू करें, या schema के आधार पर फ़ील्ड को array प्रकार घोषित करें।
import { parseStringPromise } from 'xml2js';
const parsed = await parseStringPromise(xmlText, {
explicitArray: true, // return an array even for a single element
trim: true,
explicitRoot: false,
});
2.4 सुरक्षा अनुस्मारक
अविश्वसनीय XML पार्स करने से पहले external entity अवश्य बंद करें, वरना आप XXE (स्थानीय फ़ाइलें पढ़ना, आंतरिक नेटवर्क टटोलना) भड़का सकते हैं:
// In the Node ecosystem, DTDs and external entities are usually disabled through parser options
const parserOptions = { doctype: false, externalEntities: false };
XML → JSON रूपांतरण की केवल पहली परत है; रूपांतरण XML जो हमले की सतह लाता है, उसे खत्म नहीं करता।
3. तीनों प्रारूप कहाँ बैठते हैं
| परिदृश्य | सुझाया प्रारूप | कारण |
|---|---|---|
| सार्वजनिक HTTP API | JSON | ब्राउज़र और हर भाषा द्वारा मूल रूप से समर्थित |
| हाथ से रखरखाव वाला कॉन्फ़िगरेशन | YAML | टिप्पणियाँ, इंडेंटेशन, पठनीयता |
| मज़बूत schema और namespace चाहने वाले दस्तावेज़ (SOAP, Office Open XML, SVG) | XML | संरचनात्मक क्षमताएँ और मौजूदा पारिस्थितिकी |
| परिचालन टूलिंग के साथ अंतःक्रिया (K8s, CI) | YAML | पारिस्थितिकी का डिफ़ॉल्ट |
| Persistence, कैश, लॉग | JSON / JSONL | सार्वभौमिक और निर्भरता-मुक्त |
4. कार्यान्वयन टिप्पणियाँ
import { stringify as toYaml } from 'yaml';
/**
* Converts a JSON value to YAML text while keeping Chinese characters unescaped.
* @param value The JSON value to convert
* @returns The YAML text
*/
function jsonToYaml(value: unknown): string {
return toYaml(value, {
indent: 2,
lineWidth: 0, // disable automatic wrapping so long strings are not split
defaultStringType: 'QUOTE_DOUBLE',
});
}
कुछ व्यावहारिक विकल्प:
lineWidth: 0स्वचालित wrapping बंद करता है; वरना लंबे URL पंक्तियों में बँटकर पढ़ने में कठिन हो जाते हैं;- सब कुछ दोहरे उद्धरण में रखना
NOऔर1.10जैसे मानों के गलत पढ़े जाने से बचाता है; - संवेदनशील संख्या परिशुद्धता वाले डेटा को serialize से पहले स्ट्रिंग में बदलें।
XML दिशा के लिए, एक ही मैपिंग फ़ंक्शन तय करें और "attribute उपसर्ग", "text key नाम" और "array रणनीति" को उसके signature में रखें, चारों ओर बिखेरें नहीं:
type XmlMappingOptions = {
attributePrefix: string;
textKey: string;
alwaysArray: boolean;
};
const defaultMapping: XmlMappingOptions = {
attributePrefix: '@',
textKey: '#text',
alwaysArray: false,
};
5. चेकलिस्ट
- [ ] YAML में हर "संख्या/boolean जैसा" पहचानकर्ता उद्धरण में है;
- [ ] JSON → YAML → JSON के लिए सत्यापन नमूना समुच्चय तय है और परीक्षणों से कवर है;
- [ ] जब टिप्पणियाँ बचानी हों, object round trip के बजाय Document API इस्तेमाल होता है;
- [ ] XML मैपिंग परंपरा लिखी हुई है और टीम एक ही पैरामीटर समुच्चय साझा करती है;
- [ ] अविश्वसनीय XML पार्स करते समय DTD और external entity बंद हैं;
- [ ] रूपांतरण से पहले और बाद बाइट गिनती तथा फ़ील्ड गिनती की तुलना होती है, और कोई भी असंगति अलर्ट उठाती है।
अक्सर पूछे जाने वाले प्रश्न
JSON, YAML और XML के बीच रूपांतरण की दिशा कैसे चुनूँ?
JSON को मध्यवर्ती प्रारूप बनाना पसंद करें: पहले YAML और XML को डेटा मॉडल में पार्स करें, फिर उसी मॉडल से serialize करें, पाठ दोबारा लिखने के बजाय। जब टिप्पणियाँ बचानी हों तो YAML Document API इस्तेमाल करें, और attribute या namespace की ज़रूरत से पहले एक XML मैपिंग परंपरा तय करें।
XML से JSON रूपांतरण में attribute और namespace क्यों खो जाते हैं?
JSON में attribute या namespace की कोई धारणा नहीं है, इसलिए XML attribute, उपसर्ग और namespace URI को सामान्य key में समेंटना पड़ता है, आमतौर पर @ उपसर्ग या #text node से। जैसे ही मैपिंग नियम अलग होते हैं, वही XML अलग JSON देता है और round-trip नहीं हो पाता।
JSON, YAML और XML को दीर्घकालिक दो-तरफ़ा समन्वय में रखूँ?
नहीं। टिप्पणियाँ, anchor, XML attribute और namespace प्रारूपों के पार हानिकारक हैं, और दो-तरफ़ा समन्वय में अंतर जमा होता रहता है। एक स्रोत प्रारूप चुनें और बाकी को एकबारगी निर्यात या अस्थायी दृश्य मानें।