HandyTools Hub

XML 转 JSON 转换器

即时在 XML 和 JSON 格式之间转换

在浏览器中把 XML 与 JSON 双向互转。属性、重复元素和混合文本都按广泛使用的 @ 与 #text 约定映射,因此往返转换能保留数据。粘贴 API 响应、配置文件或 RSS 订阅源即可得到可读的 JSON,也可以把 JSON 转成带缩进、合法的 XML 文档。

映射规则

XML 能表达 JSON 无法直接表达的内容:一个元素可以同时携带属性、包含文本并拥有子元素。本转换器用一组小而对称的规则来表示这些信息。

XML 结构JSON 表示
属性 id=“42”键 “@id”: “42”
叶子文本,无属性也无子元素普通字符串值
文本与属性或子元素共存”#text”: ”…”
重复的同名兄弟标签值数组
CDATA 区块文本内容

对称性才是关键:以 @ 开头的键会被写回属性,#text 会成为元素的文本,数组会展开为重复元素。正因如此,XML → JSON → XML 才是一次稳定的往返。

实操示例:一个用户文档

以下面的输入为例:

<users>
  <user id="1">
    <name>Alice</name>
    <email>alice@example.com</email>
  </user>
  <user id="2">
    <name>Bob</name>
    <email>bob@example.com</email>
  </user>
</users>

根元素名会成为最外层的键。每个 user 都带有 @id 属性和若干子元素,因此各自变成一个含 @id、name、email 的对象。由于两个 user 元素同名且互为兄弟,user 键会变成数组:

{
  "users": {
    "user": [
      { "@id": "1", "name": "Alice", "email": "alice@example.com" },
      { "@id": "2", "name": "Bob", "email": "bob@example.com" }
    ]
  }
}

内部的 name 和 email 既没有属性也没有子元素,因此各自折叠为普通字符串,而不是对象。

混合内容与 CDATA

当文本与属性同时存在时,文本会移到 #text 下。9.99 会变成 {“price”: {“@currency”: “USD”, “#text”: “9.99”}}。当文本与子元素同时存在时,所有文本片段会先拼接、再去空白,然后统一存入一个 #text,这意味着混合内容会丢失精确的交错顺序。CDATA 区块按文本对待,所以 会把原始内容作为该元素的字符串值,而不会出现实体解码的意外。

JSON 转 XML:根元素、缩进与转义

反向转换时,单键对象会成为自己的根元素,而多个键、数组或原始值会被包进 。可以选择 2 空格或 4 空格缩进。输出始终以 开头。文本会转义 &、<、>,属性值还会额外转义双引号。键名会按 XML 名称规则校验:必须以字母或下划线开头,可包含字母、数字、点、下划线、冒号和连字符。含空格或以数字开头的名称会直接报告为非法,而不会生成损坏的标记。

常见错误与局限

  • 期待带类型的值。 XML 里的所有内容都是文本,所以数字和布尔值到 JSON 中都是字符串;类型重要时请自行转换。
  • 依赖混合内容的顺序。 文本会被拼接并去除空白,子元素相对文本的位置无法还原。
  • 忘了数组需要有重复标签。 一个 JSON 对象数组会变成同名的重复元素,没有单独的列表包装。
  • 使用非法键名。 JSON 键里的空格、前导数字或其他非法字符会让 JSON → XML 转换报”非法名称”错误。
  • 以为属性顺序随意也能保持不变。 属性按 JSON 键顺序输出,在 XML → JSON 中 @ 键会插在子元素键之前,因此顺序稳定,但不一定等于原文档顺序。
  • 把超大文档塞进复制按钮。 格式化后的输出很长,剪贴板操作很笨重,这种情况请改用下载按钮。

适用场景

  • 遗留系统与 SOAP API。 许多企业服务仍返回 XML。先把响应转一次、在 JSON 查看器里看清结构,再按 @ 和 #text 键写代码。
  • 配置迁移。 pom.xml、web.config 或 Android 清单等文件转成 JSON 后,更容易用脚本做 diff 和转换。
  • RSS 与 Atom 订阅源。 订阅源条目会变成 channel 键下的 JSON 数组,无需 XML 库即可过滤和渲染。
  • 数据交换。 当下游系统只接受 XML 时,用 JSON 构建对象,让工具输出转义处理妥当的合法文档。
  • 往返校验。 把 XML 转成 JSON 再转回来,确认两个方向一致,再接入流水线。

有一点适用于以上所有场景:这套映射是一种约定,而不是通用标准。如果另一个系统习惯把属性写成内联、或把元数据包在 _attributes 之类的键下,它的 XML 转 JSON 结果不会与本工具一致,尽管两者都是合法 JSON。请按你的消费方所期望的约定来,不要假设经由别的工具往返后还能对得上。

对于大型订阅源,优先用下载而不是复制:几千个条目的格式化 JSON 很长,浏览器处理文件比处理选区更稳。转换器不做流式处理,超大文档会在转换两侧都作为文本驻留内存;如果页面变卡,请把巨型文件拆分成按条目分块处理。

相关工具

常见问题

什么时候文本会变成普通字符串,而不是 #text?

当一个元素既没有属性也没有子元素时,它会直接折叠为去掉首尾空白后的纯文本字符串。一旦该元素同时带有属性或子元素,文本就会改存到 #text 键下,因为对象里还有别的键与它并列。

混合内容里文本夹在子元素之间会怎样?

元素内所有文本节点会先被拼接、去除首尾空白,然后统一存入一个 #text。原始的交错顺序会丢失,所以 <p>你好 <b>世界</b> 再见</p> 只得到 #text "你好 再见",而不会按位置还原。

JSON 有多个顶层键时,用什么根元素?

单键对象会直接用它自己的键名作为根元素。其他情况——多个键、数组或原始值——都会被包进名为 root 的元素。输出文档始终以 version 1.0、UTF-8 的 XML 声明开头。

实体和 CDATA 区块会被解码吗?

文本和属性值中的命名实体与数字字符实体会被解码为对应字符。CDATA 区块按文本内容处理,因此它会像普通文本一样进入 #text,或在纯净叶子元素中折叠成普通字符串。

为什么转换后数字和布尔值都变成了字符串?

XML 本身没有类型概念,所有内容都是文本,因此 42 会变成 "42",true 会变成 "true"。如果下游需要真正的数字或布尔值,请在拿到 JSON 后自行转换。

键名不合法时会发生什么?

JSON → XML 方向会校验键名是否符合 XML 命名规则:必须以字母或下划线开头,只能包含字母、数字、点、下划线、冒号和连字符。含空格或以数字开头的键会直接报告为非法名称,而不是生成损坏的标记。

由 HandyTools Hub 团队审校 · 最后更新