XML 和 JSON 是软件开发中使用最广泛的两种数据交换格式。虽然 JSON 已成为 Web API 的主流选择,但 XML 在许多企业级和文档导向的场景中仍然不可或缺。本指南提供全面的对比分析,包含并排示例、详细功能对比表、性能基准测试和实用的迁移模式。
使用我们的免费 XML 格式化工具即时格式化和验证 XML →
快速解答:应该使用哪个?
使用 JSON:构建 REST API、Web 应用、配置文件,或使用 NoSQL 数据库时。JSON 更轻量、解析更快,且在 JavaScript 中原生支持。
使用 XML:需要文档标记、命名空间、模式验证、XSLT 转换,或与企业系统(SOAP、RSS/Atom、SVG、XHTML)交互时。XML 擅长表示混合内容和自描述文档。
语法对比:相同数据,两种格式
以下是用 XML 和 JSON 两种格式表达的相同数据结构:
XML
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book isbn="978-0-13-468599-1" category="programming">
<title lang="en">The Pragmatic Programmer</title>
<authors>
<author>David Thomas</author>
<author>Andrew Hunt</author>
</authors>
<year>2019</year>
<price currency="USD">49.95</price>
<inStock>true</inStock>
<tags>
<tag>programming</tag>
<tag>best-practices</tag>
<tag>career</tag>
</tags>
</book>
</bookstore>JSON
{
"bookstore": {
"books": [
{
"isbn": "978-0-13-468599-1",
"category": "programming",
"title": "The Pragmatic Programmer",
"titleLang": "en",
"authors": [
"David Thomas",
"Andrew Hunt"
],
"year": 2019,
"price": 49.95,
"priceCurrency": "USD",
"inStock": true,
"tags": ["programming", "best-practices", "career"]
}
]
}
}功能对比表
| 特性 | XML | JSON |
|---|---|---|
| 模式验证 | 支持 — XSD、DTD、RelaxNG(非常强大) | 支持 — JSON Schema(较不成熟) |
| 命名空间 | 支持 — 内置命名空间机制 | 不支持 — 无原生命名空间概念 |
| 注释 | 支持 — <!-- 注释 --> | 不支持 — 标准 JSON 不允许注释 |
| 属性 | 支持 — 元素可以拥有属性 | 不支持 — 只有键值对 |
| CDATA 区段 | 支持 — 用于原始/未转义内容 | 不支持 — 所有字符串都需转义 |
| 查询语言 | XPath、XQuery(功能强大) | JSONPath、jq(较简单) |
| 数据大小 | 较大 — 冗长的标签增加开销 | 较小 — 最少语法,更少开销 |
| 可读性 | 良好 — 自描述的标签 | 良好 — 简洁,视觉噪音少 |
| 解析速度 | 较慢 — 复杂的 DOM/SAX 解析 | 较快 — 语法简单,JS 原生支持 |
| 浏览器支持 | 良好 — DOMParser、XSLT 处理器 | 优秀 — 原生 JSON.parse/stringify |
| 流式处理 | 支持 — SAX、StAX 处理大文件 | 有限 — 需要流式处理库 |
| 内置验证 | 强大 — DTD、XSD 强制约束结构 | 基本 — JSON Schema 是可选的 |
| 转换能力 | XSLT — 强大的转换语言 | 无原生等价物 — 需用代码实现 |
| 混合内容 | 支持 — 文本和元素可以交错 | 不支持 — 不适用于混合内容 |
| 元数据 | 处理指令、属性、注释 | 无内置元数据机制 |
| 数据类型 | 所有值默认为字符串 | 字符串、数字、布尔值、null、数组、对象 |
| 编码声明 | 支持 — <?xml encoding="UTF-8"?> | 不支持 — 默认 UTF-8 |
| 元素顺序 | 保留 — 顺序有意义 | 对象无序,数组有序 |
何时使用 JSON
- REST API — JSON 是现代 Web API 的通用载荷格式(fetch、Axios、GraphQL)
- 配置文件 — package.json、tsconfig.json、.eslintrc.json、composer.json
- NoSQL 数据库 — MongoDB、CouchDB、DynamoDB 原生存储类 JSON 文档
- Web 应用 — JavaScript/TypeScript 无需依赖即可原生解析 JSON
- 实时数据 — WebSocket 消息、Server-Sent Events 通常使用 JSON
- 移动端 API — 更小的载荷意味着在移动网络上更快的传输
// REST API response (JSON)
{
"status": "success",
"data": {
"users": [
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob", "email": "bob@example.com" }
],
"pagination": { "page": 1, "total": 42 }
}
}
// package.json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"dev": "next dev",
"build": "next build"
},
"dependencies": {
"react": "^19.0.0",
"next": "^15.0.0"
}
}何时使用 XML
- SOAP Web 服务 — 企业级 API 仍广泛使用基于 XML 的 SOAP 协议
- RSS/Atom 订阅 — 内容聚合格式基于 XML
- SVG 图形 — 可缩放矢量图形是 XML 词汇表
- XHTML/HTML5 — 严格的 XHTML 序列化使用 XML 语法
- 企业集成 — 医疗(HL7/FHIR)、金融(FIX、XBRL)、政府(UBL)
- 文档标记 — DocBook、DITA、TEI 用于结构化文档
- Office 文档 — OOXML(.docx、.xlsx)和 ODF(.odt)基于 XML
- 带验证的配置 — Maven pom.xml、Spring XML、Android 清单
<!-- SOAP Request -->
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetStockPrice xmlns="http://example.com/stocks">
<StockName>GOOG</StockName>
</GetStockPrice>
</soap:Body>
</soap:Envelope>
<!-- RSS Feed -->
<rss version="2.0">
<channel>
<title>DevToolBox Blog</title>
<link>https://viadreams.cc/en/blog</link>
<item>
<title>XML vs JSON Comparison</title>
<description>Complete guide...</description>
</item>
</channel>
</rss>
<!-- SVG -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="#3b82f6" />
<text x="50" y="55" text-anchor="middle" fill="white">SVG</text>
</svg>
<!-- Maven pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</project>性能基准测试
处理相同数据集的典型性能特征(近似值,实际结果因实现和数据而异):
| 指标 | XML | JSON |
|---|---|---|
| 解析时间(1MB 文件) | ~50–80ms | ~15–30ms |
| 文件大小(相同数据) | ~1.0x(基准) | ~0.5–0.7x |
| 内存使用(DOM) | 约为文档大小的 3–5 倍 | 约为文档大小的 2–3 倍 |
| 序列化速度 | 中等 | 快速(JSON.stringify) |
| 流式解析(1GB) | SAX:高效、低内存 | 需要外部库支持 |
注意:XML 流式解析器(SAX/StAX)可以用恒定内存处理超大文件。JSON 流式解析也可行,但需要 json-stream 或 ijson 等库。对于小于 100KB 的载荷,差异可以忽略不计。
不同语言中的解析方式
JavaScript / TypeScript
// --- JSON parsing (built-in) ---
const jsonStr = '{"name":"Alice","age":30}';
const obj = JSON.parse(jsonStr);
console.log(obj.name); // "Alice"
// Serialize back
const output = JSON.stringify(obj, null, 2);
// --- XML parsing (browser) ---
const xmlStr = '<user><name>Alice</name><age>30</age></user>';
const parser = new DOMParser();
const doc = parser.parseFromString(xmlStr, 'text/xml');
const name = doc.querySelector('name')?.textContent; // "Alice"
// --- XML parsing (Node.js with xml2js) ---
import { parseStringPromise } from 'xml2js';
const result = await parseStringPromise(xmlStr);
console.log(result.user.name[0]); // "Alice"Python
import json
import xml.etree.ElementTree as ET
# --- JSON ---
json_str = '{"name": "Alice", "age": 30}'
data = json.loads(json_str)
print(data["name"]) # Alice
# Serialize
output = json.dumps(data, indent=2)
# --- XML ---
xml_str = '<user><name>Alice</name><age>30</age></user>'
root = ET.fromstring(xml_str)
print(root.find('name').text) # Alice
# --- XML with xmltodict (pip install xmltodict) ---
import xmltodict
doc = xmltodict.parse(xml_str)
print(doc['user']['name']) # AliceJava
// --- JSON with Jackson ---
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = mapper.readValue(
"{\"name\":\"Alice\",\"age\":30}",
Map.class
);
System.out.println(data.get("name")); // Alice
// --- XML with Jackson XML ---
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
XmlMapper xmlMapper = new XmlMapper();
Map<String, Object> xmlData = xmlMapper.readValue(
"<user><name>Alice</name><age>30</age></user>",
Map.class
);
// --- XML with DOM ---
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse(
new InputSource(new StringReader(xmlStr))
);
String name = doc.getElementsByTagName("name")
.item(0).getTextContent(); // AliceGo
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
// --- JSON ---
type User struct {
Name string `json:"name" xml:"name"`
Age int `json:"age" xml:"age"`
}
func main() {
// JSON
jsonStr := []byte(`{"name":"Alice","age":30}`)
var user User
json.Unmarshal(jsonStr, &user)
fmt.Println(user.Name) // Alice
// XML
xmlStr := []byte(`<user><name>Alice</name><age>30</age></user>`)
var xmlUser User
xml.Unmarshal(xmlStr, &xmlUser)
fmt.Println(xmlUser.Name) // Alice
}迁移:XML 到 JSON 转换模式
由于两者的根本差异,将 XML 转换为 JSON 并不总是简单直接的。以下是常见的模式和注意事项:
简单元素
<!-- XML -->
<user>
<name>Alice</name>
<age>30</age>
<active>true</active>
</user>
// JSON (straightforward mapping)
{
"name": "Alice",
"age": 30,
"active": true
}属性
<!-- XML with attributes -->
<product id="123" category="electronics">
<name>Laptop</name>
<price currency="USD">999.99</price>
</product>
// JSON — Convention 1: prefix with @
{
"@id": "123",
"@category": "electronics",
"name": "Laptop",
"price": {
"@currency": "USD",
"#text": 999.99
}
}
// JSON — Convention 2: flatten
{
"id": "123",
"category": "electronics",
"name": "Laptop",
"price": 999.99,
"priceCurrency": "USD"
}混合内容
<!-- XML mixed content (text + elements interleaved) -->
<p>This is <b>bold</b> and <i>italic</i> text.</p>
// JSON — No clean way to represent this!
// Option 1: HTML string
{ "p": "This is <b>bold</b> and <i>italic</i> text." }
// Option 2: Array of segments (verbose)
{
"p": [
{ "type": "text", "value": "This is " },
{ "type": "b", "value": "bold" },
{ "type": "text", "value": " and " },
{ "type": "i", "value": "italic" },
{ "type": "text", "value": " text." }
]
}重复元素
<!-- XML repeated elements -->
<users>
<user>Alice</user>
<user>Bob</user>
<user>Charlie</user>
</users>
// JSON — Always use arrays for repeated elements
{
"users": ["Alice", "Bob", "Charlie"]
}
// Watch out: single-element case in XML
<users>
<user>Alice</user>
</users>
// Some converters output a string instead of array!
// BAD: { "users": { "user": "Alice" } }
// GOOD: { "users": { "user": ["Alice"] } }
// Always force arrays for elements that can repeat.重要提示:XML 转 JSON 没有唯一"正确"的方式。不同的转换器使用不同的约定(如属性的表示:@attr、_attr 或 $attr)。务必记录你的转换约定并保持一致。
XML 和 JSON 的替代方案
虽然 XML 和 JSON 占据主导地位,但还有一些格式可以满足特定需求:
| 格式 | 描述 |
|---|---|
| YAML | 对人类友好的配置格式。广泛用于 Docker Compose、Kubernetes、CI/CD。是 JSON 的超集,但支持注释、多行字符串和更简洁的语法。 |
| TOML | 最小化、无歧义的配置格式。用于 Rust(Cargo.toml)、Python(pyproject.toml)。比 JSON 更适合配置,比 YAML 更简单。 |
| Protocol Buffers | Google 的二进制序列化格式。比 JSON 小 3–10 倍,解析速度更快。需要 Schema(.proto 文件)。适合微服务通信。 |
| MessagePack | 与 JSON 数据类型兼容的二进制格式。比 JSON 更小更快。无需 Schema。适合缓存、服务间通信。 |
| Apache Avro | 支持 Schema 演化的二进制格式。在大数据领域流行(Hadoop、Kafka)。Schema 随数据发送,支持丰富的类型信息。 |
常见问题
JSON 总是比 XML 快吗?
在解析方面,JSON 通常比 XML DOM 解析快 2–4 倍,因为 JSON 的语法更简单。但是,XML 的 SAX/StAX 流式解析器处理超大文件时比非流式 JSON 解析器更高效。对于小于 100KB 的载荷,速度差异可以忽略。JSON 真正的性能优势来自更小的文件大小,减少了网络传输时间。
JSON 能完全替代 XML 吗?
不能。JSON 无法表示混合内容(文本与标记交错),不支持命名空间,缺少像 XSLT 这样的原生转换语言,且模式验证能力不如 XSD。许多行业标准(SOAP、RSS、SVG、Office 格式、医疗 HL7)都基于 XML,无法被替代。JSON 更适合数据交换,XML 更适合文档。
为什么 REST API 使用 JSON 而不是 XML?
REST API 采用 JSON 因为:(1) 浏览器中的 JavaScript 可原生解析;(2) 载荷比 XML 更小;(3) 语法更简单、更易读;(4) 可直接映射到常见的编程数据结构(对象、数组)。SOAP API 历来使用 XML,但大多数新 API 更倾向于使用 JSON 的 REST。
配置文件应该用 XML 还是 JSON?
对大多数项目来说,JSON(或 YAML/TOML)因其简洁性和工具支持而更受青睐。但 XML 仍用于需要模式验证的复杂配置(Maven pom.xml、Spring XML、Android 清单)。如果配置中需要注释,请使用 YAML、TOML 或 XML——标准 JSON 不支持注释。
如何将 XML 转换为 JSON?
使用适合你语言的库:<code>xml2js</code>(Node.js)、<code>xmltodict</code>(Python)、<code>Jackson XML</code>(Java)或 <code>encoding/xml</code>(Go)。注意 XML 属性、命名空间和混合内容在 JSON 中没有直接等价物,所以要选择一种约定(如用 <code>@attr</code> 表示属性)并加以文档化。我们的 XML 格式化工具可以帮你在转换前检查 XML 结构。