JSON 与 XML 的转换:两种数据格式的世纪之争
什么是 JSON 和 XML?
用一句话概括:JSON 和 XML 是过去二十多年里 Web 数据交换的两大”通用语”。
XML(eXtensible Markup Language)出生于 1998 年,W3C 背书,一出生就带着”企业级”的光环。它用尖括号标签包裹数据,像 HTML 的亲兄弟。
JSON(JavaScript Object Notation)晚了几年——Douglas Crockford 在 2001 年前后把它从 JavaScript 里”提取”出来,变成了语言无关的轻量格式。本质上就是花括号、方括号加键值对,简单到一张餐巾纸就能写完它的语法规范。
把同一个数据用两种格式写出来,差别一目了然。下面是一份人员信息:
JSON:
{
"person": {
"name": "张三",
"age": 30,
"skills": ["Java", "Python"],
"address": {
"city": "北京",
"zip": "100000"
}
}
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<name>张三</name>
<age>30</age>
<skills>
<skill>Java</skill>
<skill>Python</skill>
</skills>
<address>
<city>北京</city>
<zip>100000</zip>
</address>
</person>
一眼看去,JSON 更短、更干净。XML 多了一堆开闭标签,同样的数据体积大了将近一倍。但 XML 在这里藏了一些 JSON 没有的东西——比如你可以给 <person> 加属性(<person id="001" type="employee">),JSON 要做到同样的效果就得嵌套一层额外的字段。
我记得 2013 年前后,公司内部有个服务迁移项目——把一套 SOAP 接口改成 RESTful。当时团队里一个老架构师坚持保留 XML,“你们年轻人不知道,XML Schema 能在编译期就帮你拦住一半的 bug”。我当时不以为然,觉得 JSON 又快又省事。后来一个金融客户对接时,对方发来的 XSD 校验文件精确到了每个字段的 minOccurs、maxLength、pattern 正则——那一刻我理解了那位架构师的意思。
JSON 和 XML 各自的工作原理
JSON 的数据模型
JSON 只有六种数据类型:字符串、数字、布尔值、null、对象、数组。没有日期类型(通常用 ISO 8601 字符串代替),没有二进制(用 Base64)。
解析 JSON 就是把它还原成对应语言的原生数据结构——在 JavaScript 里 JSON.parse() 出的是 Object 和 Array,在 Python 里 json.loads() 出的是 dict 和 list。几乎零阻抗匹配,这也是 JSON 在 Web 前端领域碾压 XML 的根本原因。
XML 的树模型
XML 比 JSON 复杂不少。同一个 XML 文档,你至少可以用三种方式去理解它:
- DOM(Document Object Model):把整个 XML 读进内存,构建一棵完整的节点树。好处是能随机访问任何节点,坏处是大文件直接爆内存。
- SAX(Simple API for XML):基于事件的流式解析,逐个标签触发回调。省内存但写起来反人类——你得像状态机一样跟踪”当前在解析哪个节点”。
- XPath:像操作文件路径一样
//person/address/city提取数据,配合 XSLT 还能做数据转换和渲染。
我第一次用 XPath 的时候觉得这东西像魔法——一句表达式就能从几百行的 XML 里精准抽出想要的字段,比写几十行 for 循环遍历 JSON 嵌套爽多了。但 XPath 的学习曲线摆在那里,很多人望而却步。
核心特性对比
| 特性 | JSON | XML |
|---|---|---|
| 数据类型 | 6 种(string, number, boolean, null, array, object) | 全是文本,类型靠 Schema 定义 |
| 体积 | 精简,无冗余标签 | 较大,开闭标签重复 |
| 可读性 | 极好,类 JavaScript 语法 | 标签过多,嵌套深时易迷失 |
| Schema 校验 | JSON Schema(可选,普及度一般) | XML Schema / DTD(成熟,企业级) |
| 命名空间 | 不支持 | 支持(避免元素名冲突) |
| 注释 | 不支持(规范禁止) | 支持 <!-- 注释 --> |
| 流式解析 | 有限(逐行 JSON Lines) | 成熟(SAX, StAX) |
| 二进制支持 | 无(需 Base64) | 无(需 Base64 或 CDATA) |
| 查询语言 | JSONPath(非标准) | XPath(W3C 标准) |
| 转换语言 | 无 | XSLT |
| 解析开销 | 极低 | 较高 |
XML 有个设计让我一直觉得遗憾——JSON 当年故意没加注释功能,Crockford 的理由是”注释会被拿来放处理指令,破坏数据纯净性”。听起来有道理,但实际工作中配置文件里不能写注释实在是太痛苦了。XML 的 <!-- --> 在这方面就贴心很多。
实际应用场景
1. REST API — JSON 的主场
现在打开任何一个公开 API,十有八九返回 JSON。为什么?前端 JavaScript 直接 JSON.parse(response) 就能用,零转换成本。如果换成 XML,你得引入 DOMParser 或第三方库、写 XPath 提取逻辑,开发体验差一个量级。
这也是为什么 REST 取代 SOAP 的时候,JSON 跟着一起赢了——不是 JSON 比 XML 优秀多少,而是 JSON 和 REST 的轻量哲学天然对味。
2. 金融和政府系统 — XML 最后的堡垒
说个真实经历。2020 年帮一个银行客户做系统集成,他们的报文格式要求必须是 ISO 20022——一套基于 XML 的金融数据交换标准。每个字段都有严格的 XSD 定义,类型、长度、枚举值全部写死在 Schema 里。数据发过去之前跑一遍 XSD 校验,格式问题一目了然,根本不用等到运行时才发现。
这也是 XML 至今不倒的核心原因:当你需要跨组织、长周期、强约束的数据交换时,XML Schema 提供的编译期保障是 JSON 无法企及的。SAML(单点登录断言)、XBRL(财务报告)、OFX(开放金融交换)全都建立在 XML 之上。
3. RSS / Atom — 内容聚合的暗线
你以为 RSS 死了?维基百科、arXiv、各大博客平台的 RSS Feed 每天被成千上万的阅读器和爬虫消费。RSS 本质上就是一个标准化的 XML 文档,按约定好的标签结构(<channel>、<item>、<pubDate>)组织内容。因为结构固定、工具链成熟,二三十年之后到现在还在稳定运转。
4. SOAP Web 服务 — 遗留系统的脊梁
SOAP 可能是被嘲讽最多的技术之一了。但你得承认,像 Salesforce、SAP 这类企业级平台的 API 至今提供 SOAP 接口。原因无他:WSDL 描述文件能生成强类型客户端代码,配合 WS-Security 提供标准化的加密签名,省掉大量手写安全逻辑的工作。你可以讨厌 SOAP 的笨重,但它在企业集成领域的位置目前还没有 JSON 方案能完全替代。
5. 配置文件
Maven 的 pom.xml、Android 的 AndroidManifest.xml、Spring 的 bean 配置——XML 在某些技术栈的配置文件地位根深蒂固。不过说实话,新项目里越来越多在用 YAML 了(Kubernetes、Docker Compose、GitHub Actions),XML 的身影在缓慢退场。
JSON 与 XML 的互相转换
两种格式之间的转换,本质上是一个结构映射的过程:
JSON对象 → XML 元素
JSON键名 → XML 标签名
JSON数组 → 重复的 XML 子元素
JSON属性值 → XML 文本节点
但说是映射,坑不少。举个例子:XML 元素可以同时有文本内容和子元素(混合内容),比如 <desc>这是一段<b>加粗</b>的文字</desc>——这种结构 JSON 没法无损表达,最常见的妥协方案是把文本和子元素拆成独立的字段。另一个坑是 XML 属性——<book isbn="12345"> 转 JSON 时,属性放哪里?有些转换器用 @isbn,有些用 _attributes 对象,没有统一标准。
所以,JSON 到 XML 的转换在简单场景下很丝滑,但碰上混合内容、命名空间、CDATA 块、处理指令这些 XML 专属特性时,就必然会丢失信息。
常见误区
误区一:JSON 已经完全取代了 XML
这话对前端领域基本没错,但对企业集成和金融系统来说完全不对。XML 的 Schema 校验、命名空间、XSLT 转换,在某些场景里不是”可选的加分项”,而是刚需。两者会长期共存——就像 COBOL 依然在银行核心系统里跑一样,不是因为它先进,而是因为它被证明了可靠。
误区二:JSON 转 XML 是无损可逆的
不是。两种格式在表达能力上有交集但不重合。JSON 数组、null、数字类型在 XML 里没有原生对应;XML 的属性、命名空间、混合内容、处理指令在 JSON 里也没有标准表达方式。我们的工具在做转换时会尽量保留信息,但来回转换(JSON → XML → JSON)通常不是恒等变换。
误区三:XML 解析一定很慢
现代 XML 解析器(比如 Java 的 Aalto、C++ 的 pugixml)性能并不差,尤其流式解析模式下。真正拖慢的是 DOM 解析——把整个文档构建成内存树。大文件用 SAX/StAX 就行,就像大 JSON 文件也建议用流式解析而非 JSON.parse 一把梭。
JSON vs XML vs YAML vs Protobuf
| JSON | XML | YAML | Protobuf | |
|---|---|---|---|---|
| 易读性 | 好 | 中(标签噪音大) | 最好 | 差(二进制) |
| 体积 | 小 | 大 | 中 | 最小 |
| Schema | 可选 | 成熟 | 可选 | 必选(.proto) |
| 解析速度 | 快 | 较慢 | 慢 | 极快 |
| 适用场景 | Web API、前端 | 企业集成、金融 | 配置文件、DevOps | 微服务间 RPC |
| 注释支持 | 否 | 是 | 是 | 是 |
Protobuf 这类二进制序列化格式在性能上确实碾压 JSON 和 XML,但它们牺牲了人类可读性。如果你需要在 Chrome DevTools 里直接看响应的内容、在 Postman 里手动调试接口,JSON 永远是首选。
常见问题
Q: JSON 和 XML 哪个更好?
这不是一个”谁更好”的问题——是”在什么场景下谁更合适”。做 Web API,JSON 几乎是最优解;做企业间金融报文交换,XML Schema 的约束能力无可替代;做微服务内部通信,Protobuf 可能更香。选格式之前,先想清楚你的主要约束是开发效率、数据完整性、传输性能还是跨组织协作。
Q: 什么时候应该主动使用 XML?
当你的数据需要跨组织长期维护、需要严格的 Schema 校验、或者对接的遗留系统只认 XML 的时候。另外,如果你的数据里包含文档结构(比如带格式的文本、表格),XML 的混合内容模型天然更适合这类半结构化数据。
Q: XML 的属性(attribute)和元素(element)有什么区别?该用哪个?
属性适合放简短、不可重复的元数据(比如 ID、类型标签),元素适合放实际内容数据。XML 社区有个非正式共识:如果你删掉这个信息后数据就不完整了,用元素;如果只是修饰性信息,可以用属性。不过说实话,这条规则的主观性很强,同一个数据在不同 XML 设计里可能一个用属性一个用元素,这也是 JSON 拥趸攻击 XML “过度设计”的靶子之一。
Q: JSON 为什么不能有注释?
Crockford 的原话是:“注释会被用来放解析指令,这破坏了互操作性。“听起来有点强迫症,但他当时的目标是让 JSON 成为全世界最不可误读的数据格式。JSON5、Hjson 等变体加了注释支持,但不是标准 JSON,使用是有限制的。
Q: 我的项目应该同时支持 JSON 和 XML 输出吗?
如果你的 API 会被各种客户端消费——前端用 JSON,某个企业网关用 XML——同时支持两种格式是有价值的。通常做法是在同一个接口上通过 Accept 请求头协商格式:Accept: application/json 返回 JSON,Accept: application/xml 返回 XML。Spring Boot、Express 等主流框架都有现成的支持,加一个注解或中间件就行。