تبدیل JSON به XML زمانی ضروری میشود که یک API یا برنامه مدرن داده را به شکل JSON تولید میکند، اما سامانه مقصد، سرویس سازمانی، نرمافزار قدیمی یا پروتکل تبادل اطلاعات فقط XML میپذیرد. این تبدیل برخلاف تغییر ساده چند علامت نیست؛ JSON و XML مدل داده متفاوتی دارند. JSON بر object، array و مقدارهای نوعدار تکیه میکند، در حالی که XML با element، attribute، متن، ترتیب فرزندان و namespace کار میکند. بنابراین پیش از تبدیل باید برای نام عنصر ریشه، نمایش آرایهها، مقدار null، نوع داده، کلیدهای نامعتبر XML و objectهای تودرتو قرارداد روشنی داشته باشید.
پاسخ سریع: برای تبدیل JSON به XML، هر کلید object معمولاً به یک element، مقدارهای ساده به متن element و objectهای داخلی به elementهای تودرتو تبدیل میشوند. اعضای array باید با یک نام تکرارشونده مانند
itemیا نام مفرد مشخص نمایش داده شوند. مقدار null، attributeها، namespaceها و نوع دادهها نگاشت استاندارد و یکتایی ندارند؛ بنابراین تبدیل قابلاعتماد به Schema یا تنظیمات صریح نیاز دارد.
تفاوت بنیادی JSON و XML چیست؟
JSON یک مدل داده نسبتاً مستقیم دارد: object مجموعهای از جفتهای کلید و مقدار است، array مجموعهای مرتب از اعضا است و مقدارها میتوانند String، Number، Boolean، null، object یا array باشند. XML در مقابل یک درخت از elementها است که هر element میتواند attribute، متن و فرزند داشته باشد. XML همچنین ترتیب elementها، namespace و محتوای ترکیبی را پشتیبانی میکند.
| ویژگی | JSON | XML |
|---|---|---|
| ساختار اصلی | Object و Array | Element و Attribute |
| عنصر ریشه | Object، Array یا مقدار ساده | دقیقاً یک Document Element |
| نوع داده | Number، Boolean، null و String قابلتمایزند | متن element ذاتاً String است مگر Schema نوع را تعریف کند |
| نام کلید | تقریباً هر String | باید XML Name معتبر باشد |
| آرایه | نوع مستقل | معمولاً با elementهای تکراری مدل میشود |
| Namespace | مفهوم داخلی ندارد | قابلیت اصلی XML است |
| ترتیب | ترتیب Array معنادار است | ترتیب elementهای فرزند معنادار است |
به همین دلیل، خروجی XML فقط زمانی قابلپیشبینی است که قواعد نگاشت از قبل تعیین شوند.
سادهترین نمونه تبدیل JSON به XML
ورودی JSON:
{
"user": {
"id": 101,
"name": "سارا",
"active": true
}
}
یک خروجی ممکن:
<user>
<id>101</id>
<name>سارا</name>
<active>true</active>
</user>
در این نگاشت، کلید user ریشه XML شده، هر کلید داخلی یک element ساخته و مقدار ساده به متن element تبدیل شده است. نوع Number و Boolean در متن XML قابل مشاهده است، اما بدون XML Schema مصرفکننده فقط متن دریافت میکند.
اگر JSON عنصر ریشه مشخص نداشته باشد چه میشود؟
یک سند XML معتبر باید دقیقاً یک element ریشه داشته باشد. اما JSON میتواند مستقیماً array باشد:
[
{"id": 1, "name": "کتاب"},
{"id": 2, "name": "دفتر"}
]
برای XML باید یک wrapper انتخاب شود:
<products>
<product>
<id>1</id>
<name>کتاب</name>
</product>
<product>
<id>2</id>
<name>دفتر</name>
</product>
</products>
نامهای products و product از خود JSON قابل استخراج قطعی نیستند. یک مبدل عمومی ممکن است از root و item استفاده کند، اما برای قراردادهای واقعی بهتر است این نامها صریح تنظیم شوند.
نگاشت Objectهای تودرتو
Object داخلی معمولاً به element تودرتو تبدیل میشود:
{
"order": {
"id": "A-500",
"customer": {
"name": "مریم",
"city": "تبریز"
}
}
}
<order>
<id>A-500</id>
<customer>
<name>مریم</name>
<city>تبریز</city>
</customer>
</order>
این حالت معمولاً بدون ابهام است، مگر اینکه کلیدها برای نام element نامعتبر باشند یا مقصد انتظار داشته باشد برخی فیلدها attribute باشند.
آرایههای JSON چگونه به XML تبدیل میشوند؟
XML نوع مستقلی به نام Array ندارد. رایجترین روش، تکرار یک element برای هر عضو آرایه است.
{
"tags": ["json", "xml", "conversion"]
}
مدل wrapper و item:
<tags>
<item>json</item>
<item>xml</item>
<item>conversion</item>
</tags>
مدل element تکراری بدون wrapper:
<tag>json</tag>
<tag>xml</tag>
<tag>conversion</tag>
مدل دوم فقط درون یک ریشه بزرگتر معتبر است. انتخاب بین این دو مدل به Schema مقصد بستگی دارد.
آرایهای از objectها
{
"items": [
{"sku": "P10", "qty": 2},
{"sku": "P22", "qty": 1}
]
}
<items>
<item>
<sku>P10</sku>
<qty>2</qty>
</item>
<item>
<sku>P22</sku>
<qty>1</qty>
</item>
</items>
آرایه خالی
آرایه خالی میتواند به element خالی، element خودبسته یا حذف کامل عنصر تبدیل شود:
<items></items>
یا:
<items />
این دو از نظر XML معمولاً معادلاند، اما حذف کامل items از نظر معنایی متفاوت است.
مقدار null در XML چگونه نمایش داده میشود؟
JSON مقدار صریح null دارد، اما XML بدون Schema معادل یکتایی برای آن ندارد. گزینههای متداول:
| روش | نمونه | نکته |
|---|---|---|
| Element خالی | <note /> | ممکن است با String خالی اشتباه شود |
| حذف element | بدون خروجی | مقدار گمشده و null یکی میشوند |
| متن قراردادی | <note>null</note> | بهصورت String دیده میشود |
| XML Schema Instance | <note xsi:nil="true" /> | به namespace و قرارداد Schema نیاز دارد |
اگر round-trip دقیق لازم است، استفاده از xsi:nil یا metadata صریح مطمئنتر است. در تبدیل عمومی باید سیاست null قابل انتخاب باشد.
کلیدهای نامعتبر JSON برای نام XML
کلید JSON میتواند شامل فاصله، نقطه، کاراکترهای خاص یا شروع عددی باشد:
{
"first name": "سارا",
"2026-status": "active",
"user.email": "sara@example.test"
}
همه این نامها الزاماً element name مناسب نیستند. راهکارها:
- Normalize کردن نام، مانند تبدیل فاصله و نقطه به زیرخط.
- افزودن پیشوند به نام شروعشونده با عدد.
- استفاده از element عمومی و نگهداری کلید در attribute.
- رد کردن ورودی و درخواست Schema معتبر.
مدل element عمومی:
<entry key="first name">سارا</entry>
<entry key="2026-status">active</entry>
این روش نام اصلی را حفظ میکند، اما ساختار XML مقصد را تغییر میدهد.
Element یا Attribute؛ کدام بهتر است؟
JSON تفاوت attribute و element را نمیشناسد. تبدیلکننده باید تصمیم بگیرد همه کلیدها element شوند یا برخی به attribute تبدیل شوند.
{
"product": {
"id": "P10",
"name": "کیبورد",
"price": 1250000
}
}
مدل element:
<product>
<id>P10</id>
<name>کیبورد</name>
<price>1250000</price>
</product>
مدل attribute:
<product id="P10" price="1250000">
<name>کیبورد</name>
</product>
برای دادهای که ممکن است تکرار، ساختار داخلی یا متن طولانی داشته باشد element انعطاف بیشتری دارد. Attribute برای metadata کوتاه و بدون ساختار مناسب است. تبدیل خودکار همه مقدارهای ساده به attribute معمولاً توصیه نمیشود.
Escape کردن کاراکترهای ویژه XML
متن JSON ممکن است شامل کاراکترهایی باشد که در XML معنای نحوی دارند. حداقل این موارد باید escape شوند:
| کاراکتر | نمایش XML |
|---|---|
& | & |
< | < |
> | > در صورت نیاز |
" در attribute | " |
' در attribute تککوتیشنی | ' |
ورودی:
{
"message": "5 < 10 & 10 > 5"
}
خروجی صحیح:
<message>5 < 10 & 10 > 5</message>
ساخت XML با اتصال دستی String خطرناک است. بهتر است از API یا کتابخانهای استفاده شود که escaping را خودکار انجام دهد.
حفظ نوع دادهها
وقتی Number یا Boolean به متن element تبدیل میشود، نوع آن در XML خام از بین میرود:
{"count": 10, "active": true, "code": "10"}
<count>10</count>
<active>true</active>
<code>10</code>
بدون Schema مشخص نیست count عدد است و code String. راههای حفظ نوع:
- تعریف XSD برای elementها.
- افزودن attribute قراردادی مانند
type="number". - اتکا به Schema مقصد.
- پذیرش تبدیل همه مقدارها به String.
اگر قرار است XML دوباره به JSON برگردد، Schema بهترین راه برای round-trip قابلاعتماد است.
Namespace در تبدیل JSON به XML
JSON مفهوم namespace ندارد، اما XML مقصد ممکن است namespace اجباری داشته باشد:
<order xmlns="urn:example:orders">
<id>A-500</id>
</order>
namespace نباید از روی نام کلیدها حدس زده شود. URI، prefix و محل declaration باید از تنظیمات یا Schema مقصد بیاید. استفاده اشتباه از namespace میتواند XML را از نظر Syntax معتبر ولی از نظر قرارداد مقصد نامعتبر کند.
تبدیل JSON به XML در JavaScript
نمونه زیر برای آموزش، object، array و مقدارهای ساده را مدیریت میکند. برای تولید واقعی بهتر است از XML builder معتبر استفاده شود:
function escapeXml(value) {
return String(value)
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function normalizeName(name) {
let result = String(name).replace(/[^A-Za-z0-9_.-]/g, "_");
if (!/^[A-Za-z_]/.test(result)) {
result = `_${result}`;
}
return result;
}
function valueToXml(name, value) {
const tag = normalizeName(name);
if (value === null) {
return `<${tag} />`;
}
if (Array.isArray(value)) {
const items = value
.map(item => valueToXml("item", item))
.join("");
return `<${tag}>${items}</${tag}>`;
}
if (typeof value === "object") {
const children = Object.entries(value)
.map(([key, child]) => valueToXml(key, child))
.join("");
return `<${tag}>${children}</${tag}>`;
}
return `<${tag}>${escapeXml(value)}</${tag}>`;
}
function jsonToXml(input, rootName = "root") {
if (
input !== null &&
typeof input === "object" &&
!Array.isArray(input)
) {
const entries = Object.entries(input);
if (entries.length === 1) {
const [name, value] = entries[0];
return `<?xml version="1.0" encoding="UTF-8"?>` +
valueToXml(name, value);
}
}
return `<?xml version="1.0" encoding="UTF-8"?>` +
valueToXml(rootName, input);
}
این نمونه نامها را normalize میکند و array را با item نمایش میدهد. اما attribute، namespace، CDATA، mixed content، XSD و سیاست دقیق null را پوشش نمیدهد.
تبدیل JSON به XML در Python
کتابخانه استاندارد xml.etree.ElementTree از ساخت element و escaping پشتیبانی میکند:
import json
import re
import xml.etree.ElementTree as ET
def normalize_name(name):
value = re.sub(r"[^A-Za-z0-9_.-]", "_", str(name))
if not re.match(r"^[A-Za-z_]", value):
value = "_" + value
return value
def append_value(parent, name, value):
element = ET.SubElement(parent, normalize_name(name))
if value is None:
return element
if isinstance(value, dict):
for key, child in value.items():
append_value(element, key, child)
return element
if isinstance(value, list):
for item in value:
append_value(element, "item", item)
return element
if isinstance(value, bool):
element.text = "true" if value else "false"
else:
element.text = str(value)
return element
def json_to_xml(data, root_name="root"):
root = ET.Element(normalize_name(root_name))
if isinstance(data, dict):
for key, value in data.items():
append_value(root, key, value)
elif isinstance(data, list):
for item in data:
append_value(root, "item", item)
else:
root.text = str(data)
ET.indent(root, space=" ")
return ET.tostring(
root,
encoding="unicode",
xml_declaration=False
)
data = {
"order": {
"id": "A-500",
"items": [
{"sku": "P10", "qty": 2},
{"sku": "P22", "qty": 1}
]
}
}
print(json_to_xml(data, "document"))
برای فایل نهایی میتوان خروجی را با declaration و Encoding UTF-8 نوشت. در نسخههای قدیمیتر Python که ET.indent ندارند، pretty-print باید جداگانه انجام شود.
نمونه صحیح و غلط
نمونه صحیح
<product>
<name>A & B</name>
<price>250</price>
</product>
نمونه غلط به دلیل Escape نشدن
<product>
<name>A & B</name>
</product>
علامت ampersand خام باعث نامعتبرشدن XML میشود.
نمونه غلط به دلیل چند ریشه
<id>1</id>
<name>سارا</name>
یک سند XML نمیتواند دو Document Element مستقل داشته باشد. باید آنها داخل یک ریشه مشترک قرار گیرند.
خطاهای رایج در تبدیل JSON به XML
استفاده از کلید JSON بهعنوان tag بدون Validation
کلیدهایی که با عدد شروع میشوند یا کاراکتر نامعتبر دارند میتوانند XML نامعتبر بسازند. نامها را validate یا normalize کنید و نگاشت را ثبت کنید.
نادیدهگرفتن تفاوت Array و Object
اگر array مثل object با indexهای عددی تبدیل شود، elementهایی با نام نامعتبر یا ساختار غیرقابلاستفاده ایجاد میشوند. برای اعضای array نام item مشخص کنید.
تبدیل null به String
متن null با null واقعی یکسان نیست. سیاست null باید آگاهانه انتخاب شود.
از دست رفتن نوع داده
Number، Boolean و String در متن XML مشابه میشوند. برای سیستم نوعمحور باید XSD یا metadata نوع وجود داشته باشد.
Escape ناقص
مقدارهای دارای & و < میتوانند XML را خراب کنند. از XML builder استفاده کنید.
حدسزدن Namespace
namespace بخشی از قرارداد مقصد است. XML ممکن است well-formed باشد اما بهدلیل namespace اشتباه توسط مقصد رد شود.
امنیت تبدیل JSON به XML
- اندازه ورودی و عمق nesting را محدود کنید تا تبدیل بازگشتی باعث مصرف شدید حافظه یا stack نشود.
- نام elementها را validate کنید و از تزریق markup با ساخت String خام جلوگیری کنید.
- برای خروجیهای دانلودی، نام فایل و مسیر ذخیرهسازی را امن بسازید.
- داده حساس را پیش از Export حذف یا Mask کنید.
- هنگام Parse دوباره XML، قابلیتهای خطرناک مثل external entity را غیرفعال کنید.
- اگر XML به سامانه دیگری فرستاده میشود، Schema و محدودیت اندازه مقصد را رعایت کنید.
- از قرار دادن داده خام در CDATA بدون مدیریت توالی پایانی CDATA خودداری کنید.
حمله XXE معمولاً هنگام Parse XML رخ میدهد، نه هنگام ساخت ساده آن. بااینحال Pipeline تبدیل ممکن است XML تولیدشده را دوباره Parse کند؛ بنابراین تنظیم امن Parser همچنان ضروری است.
کارایی برای JSONهای بزرگ
بیشتر Parserهای معمولی ابتدا کل JSON را در حافظه میسازند و سپس XML تولید میکنند. برای فایل بزرگ، هم درخت JSON و هم رشته XML ممکن است همزمان در حافظه باشند.
- در صورت امکان از JSON streaming parser استفاده کنید.
- خروجی XML را تدریجی روی Stream بنویسید.
- Schema عناصر را از قبل مشخص کنید تا نیاز به نگهداری کل داده نباشد.
- عمق object و تعداد اعضای array را محدود کنید.
- Pretty-print را برای فایل بسیار بزرگ اختیاری کنید؛ indentation حجم و زمان پردازش را افزایش میدهد.
- در انتقال شبکهای از backpressure و نوشتن chunk-based استفاده کنید.
بهترین روشهای تبدیل JSON به XML
- Schema مقصد را اول مشخص کنید: نام ریشه، elementها، attributeها و namespaceها.
- سیاست Array را تعریف کنید: wrapper، نام item و رفتار array خالی.
- سیاست null را مستند کنید: element خالی، حذف یا xsi:nil.
- نوع داده را فراموش نکنید: برای round-trip از XSD یا metadata استفاده کنید.
- نام کلیدها را validate کنید: normalize کردن باید قابلپیشبینی باشد.
- از XML builder استفاده کنید: اتصال دستی String احتمال خطای escaping را بالا میبرد.
- Encoding را UTF-8 تنظیم کنید: برای متن فارسی و چندزبانه.
- XML نهایی را validate کنید: well-formed بودن و در صورت وجود، انطباق با XSD.
- برای داده بزرگ Stream کنید: از نگهداری چند نسخه کامل در حافظه پرهیز کنید.
چکلیست قبل از استفاده از XML خروجی
- آیا XML دقیقاً یک root element دارد؟
- آیا همه نامهای element معتبرند؟
- آیا Arrayها با قرارداد درست نمایش داده شدهاند؟
- آیا null و مقدار گمشده از هم قابل تشخیصاند؟
- آیا کاراکترهای ویژه بهدرستی Escape شدهاند؟
- آیا متن فارسی با UTF-8 سالم است؟
- آیا namespace و prefix مطابق قرارداد مقصد هستند؟
- آیا Number و Boolean در صورت نیاز نوع مشخص دارند؟
- آیا XML well-formed است؟
- آیا XML با XSD مقصد اعتبارسنجی شده است؟
- آیا اطلاعات حساس ناخواسته در خروجی وجود ندارد؟
چه زمانی تبدیل JSON به XML اتلاف اطلاعات دارد؟
اگر تبدیل بدون Schema انجام شود، نوع دادهها، تفاوت null و String خالی، نام دقیق کلیدهای normalizeشده و مدل array ممکن است در بازگشت XML به JSON قابل بازیابی نباشد. همچنین XML قابلیتهایی مانند attribute، namespace و mixed content دارد که در JSON معادل مستقیم ندارند.
برای round-trip قابلاعتماد باید قواعد تبدیل در هر دو جهت ثابت باشند. نگهداری Schema، mapping نامها و metadata نوعها از تبدیل مبهم جلوگیری میکند.
جمعبندی تبدیل JSON به XML
تبدیل JSON به XML یک نگاشت ساختاری است. Objectها معمولاً به elementهای تودرتو، arrayها به elementهای تکراری و مقدارهای ساده به متن تبدیل میشوند. اما root، نام item، null، attribute، namespace و نوع داده باید با قرارداد مشخص شوند. برای خروجی مطمئن، از XML builder استفاده کنید، نامها و Encoding را validate کنید و XML نهایی را از نظر well-formed بودن و در صورت نیاز XSD بررسی کنید.
برای تبدیل سریع داده میتوانید از ابزار داخلی تبدیل JSON به XML استفاده کنید. پیش از تبدیل، ابزار اعتبارسنج JSON خطاهای Syntax ورودی را مشخص میکند و برای بررسی خروجی نیز اعتبارسنج XML مناسب است.