前几天技术群里有个朋友问我“为什么我 XML 转 JSON 之后字段莫名其妙少了一半接口文档上明明有 id 和 version 的。”说实话这个坑我踩过太多次了。多到后来我形成一个习惯每次对接一个新系统只要看到返回的是 XML我就先把样例原文贴到转换工具里跑一遍然后对着输出数一遍字段。少一个都不行。因为 JSON 和 XML 之间的转换从来就不是翻译而是降维。你不提前搞清楚会丢什么等到线上数据对不上了再排查成本是十倍。这篇文章就把我这些年踩过的坑、用过的方案一次性摊开讲清楚。一、为什么这两种格式会长期共存很多人以为 XML 已经过时了。现实是银行、政务、保险、医疗的核心系统大量还在用 XML。这些系统动辄跑了十几年接口是当年用 SOAP/WSDL 定的没人敢动。Android 的配置、Maven 的 pom.xml、Spring 的老配置、各种报表导出全是 XML。REST API、前端、消息队列、日志、大模型工具调用几乎清一色 JSON。所以真实的工作场景往往是这样上游老系统 (XML) → 你的服务 (JSON) → 前端 / 下游 (JSON) 你的配置 (JSON) → 导出适配层 → 老系统 (XML)两个方向你都得会而且得知道每个方向会丢什么。二、核心认知转换是有损的这是整篇文章最重要的一句话。JSON 和 XML 的数据模型根本不是一回事维度JSONXML类型系统有string / number / boolean / null无一切都是文本属性 vs 子元素没有这个概念有两种承载方式数组显式[]隐式靠重复同名标签根节点不要求必须有且只有一个混合内容不支持支持文字和标签混排注释不支持支持!-- --命名空间无有xmlns只要两边模型不对齐转换就必然要做取舍。取舍就是丢信息的风险点。下面是我总结的六个最容易翻车的地方每一个都真实坑过我。三、六个必踩的坑坑 1XML 属性会被直接吞掉XML 里承载数据有两种方式personid42dept研发部nameAlice/name/personid和dept是属性name是子元素。很多轻量转换工具只处理子元素属性直接忽略于是你得到{person:{name:Alice}}id没了。这就是开头那位朋友的遭遇。怎么办转换前先肉眼扫一遍 XML看有没有keyvalue这种写法。有的话要么换一个支持属性的库比如xmltodict、fast-xml-parser它们会把属性映射成id、_id要么在上游就把属性拍平成子元素。坑 2所有值都变成字符串XML 没有类型系统。amount299.5/amount在 XML 里就是一段文本解析器不知道它是数字。所以转换结果通常是{amount:299.5,qty:2,enabled:true}全部带引号。下游代码如果直接amount * 1.05JavaScript 里会得到NaNPython 里直接TypeError。怎么办拿到 JSON 后必须做一层类型还原。要么按接口文档手写映射要么在解析层配置类型推断fast-xml-parser有parseTagValue选项。千万不要指望转换工具帮你猜类型猜错的代价比不猜更大。坑 3单条是对象多条变数组这是 XML 转 JSON 最阴险的一个坑。roottaga/tag/root转出来{root:{tag:a}}只有一条数据时tag是字符串。roottaga/tagtagb/tag/root转出来{root:{tag:[a,b]}}两条时tag变成了数组。XML 里没有任何信息能告诉解析器这个字段天生是列表。它只能根据实际出现几次来决定。于是你的代码data.root.tag.map(...)在测试环境跑得好好的上了生产遇到只有一条记录的订单直接报tag.map is not a function。怎么办在数据访问层做归一化永远当数组处理consttags[].concat(data.root.tag??[]);Java 里同理DTO 字段一律声明成ListT配合 Jackson 的JacksonXmlElementWrapper/ACCEPT_SINGLE_VALUE_AS_ARRAY。坑 4根节点名的诡异行为XML 强制要求单一根元素JSON 不要求。JSON 转 XML 时工具必须替你造一个根。不同工具的策略不一样有的是固定叫root有的是取第一个键名。我常用的一个纯前端在线工具https://leowh.com/tools/json-xml/index.html用的是后者。如果你的 JSON 顶层有多个键https://leowh.com/tools/json-xml/index.html{a:1,b:2}它会拿第一个键a当根名然后把所有顶层键塞进去?xml version1.0 encodingUTF-8?aa1/ab2/b/aa出现了两次显然不是你想要的。怎么办养成习惯JSON 顶层永远只留一个键并且显式写出你要的根元素名{request:{a:1,b:2}}这样无论用哪个工具输出都是确定的。这也是很多老接口文档的写法——最外层永远包一个Request或Service。坑 5混合内容会丢文本XML 允许文字和标签混排note重要b加粗/b内容/note绝大多数转换器只看子元素结果{note:{b:加粗}}重要和内容两段文字凭空消失了。怎么办如果你的数据里有富文本、HTML 片段、带标注的说明文字别用通用转换器。这种场景应该把内容包进![CDATA[...]]或者干脆 base64 编码后当字符串传。坑 6转义和编码JSON 字符串里的、、、转成 XML 时必须转义 → amp; → lt; → gt; → quot;反过来XML 里的amp;解回 JSON 时要还原成。漏掉这一步下游 XML 解析器会直接抛not well-formed。中文乱码则通常是编码问题XML 声明写了encodingUTF-8但文件实际是 GBK 存的。声明和实际编码必须一致这个没有捷径。四、四种方案我实际怎么选踩完坑说方案。我把日常会用到的分成四类方案典型场景优点代价在线工具纯前端临时看结构、写文档举例、排查字段零安装秒出结果数据不上传属性和类型会丢批量做不了命令行yq/xmllint本地脚本、CI 流水线可管道、可批量要装参数得查解析库xmltodict/fast-xml-parser/ Jackson进生产代码行为可控能保留属性要自己定约定有学习成本手写正则————❌ 别这么干什么时候用在线工具我的判断标准很简单这段数据我只需要看一次。比如对方甩给我一个 3000 行的 XML 报文我要快速搞清楚它的层级结构或者我在写接口文档需要一个 XML 样例的 JSON 对照。这种时候我不会去装库、写脚本那是纯粹的时间浪费。我一般直接用浏览器里的转换页面比如 https://leowh.com/tools/json-xml/index.html 。选它的理由有两个一是纯前端实现转换在浏览器本地完成数据不会发到服务器。公司报文、客户数据敢往里贴这一点比界面好看重要得多。二是支持Ctrl/Cmd Enter快捷键改一下输入立刻重算来回调结构的时候很顺手。页面上还有个加载示例按钮示例数据会跟着当前转换方向自动切换给别人演示的时候不用现编数据。但我也得说清楚它的边界它不处理 XML 属性输出值全是字符串根节点名取第一个键。拿来理解结构、做一次性验证完全够要进生产链路请用下面的方案。⚠️ 另外提醒一句用任何在线转换工具前先确认它是不是纯前端。打开浏览器开发者工具的 Network 面板点一次转换如果看到有请求带着你的数据发出去那就别贴敏感内容。命令行能批量才叫生产力本地装了 yq 的话一行搞定# XML → JSONyq-pxml-ojson resp.xml# JSON → XMLyq-pjson-oxml config.jsonyq 默认会保留属性前缀比在线工具信息更完整。配合管道做批量find./dump-name*.xml-print0|\xargs-0-I{}sh-cyq -p xml -o json {} {}.json只想看某个节点用xmllintxmllint--xpath//person/name/text()resp.xml脚本层Python 三行起步一次性的活儿我更喜欢 Python因为可以顺手做类型还原和字段归一化。简单场景标准库就够importjsonimportxml.etree.ElementTreeasETdefelem_to_dict(el):childrenlist(el)ifnotchildren:return(el.textor).strip()out{}forcinchildren:valelem_to_dict(c)ifc.taginout:# 重复标签 → 强制数组ifnotisinstance(out[c.tag],list):out[c.tag][out[c.tag]]out[c.tag].append(val)else:out[c.tag]valreturnout xml_textopen(resp.xml,encodingutf-8).read()rootET.fromstring(xml_text)print(json.dumps({root.tag:elem_to_dict(root)},ensure_asciiFalse,indent2))注意这段代码里我特意处理了重复标签才变数组的问题——但单条记录仍然是对象坑 3 没解决。要彻底解决就得靠 schema 或者显式声明哪些字段是列表。要保留属性的话用xmltodict更省心pipinstallxmltodictimportjsonimportxmltodict dataxmltodict.parse(open(resp.xml,encodingutf-8).read())print(json.dumps(data,ensure_asciiFalse,indent2))它会把属性映射成id混合内容的文本映射成#text信息基本不丢。Node.js 那边对应的是fast-xml-parsernpmi fast-xml-parserconst{XMLParser}require(fast-xml-parser);constparsernewXMLParser({ignoreAttributes:false,// 保留属性默认是丢弃的attributeNamePrefix:_,isArray:(name)[person,item].includes(name),// 显式声明数组字段});constobjparser.parse(xmlText);isArray这个选项就是专门治坑 3 的不管 XML 里出现几次输出永远是数组。生产代码Java 系怎么接老系统对接绕不开 Java。两条路JacksonXmlMapper推荐灵活XmlMapperxmlMappernewXmlMapper();xmlMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true);JsonNodenodexmlMapper.readTree(xmlBytes);StringjsonnewObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(node);ACCEPT_SINGLE_VALUE_AS_ARRAY一定要开否则单条记录的接口会随机炸。JAXB有 XSD 的时候用强类型xjc-dsrc/main/java-pcom.example.dto schema.xsd生成 POJO 之后直接unmarshal类型和数组都是确定的坑 2 和坑 3 一次性解决。代价是改 schema 比较重。五、三个真实场景场景一对接某城商行的支付回调对方返回一个带命名空间的 SOAP XML里面Order Amount299.50 CurrencyCNY全是属性。第一版我用在线工具转完直接落库结果金额字段全是空的——属性被吞了坑 1。换成xmltodict之后属性以Amount的形式出来了再加一层字段映射和Decimal转换坑 2问题解决。教训先看报文长相再选工具。有属性的报文在线工具一开始就不该进入候选。场景二给前端造 Mock 数据前端同事手上只有甲方给的 XML 样例需要 JSON 格式来写 TypeScript 类型定义。这种事我直接在浏览器里转30 秒完事。转完顺手把单条对象/多条数组的地方标出来提醒他类型定义要写成T | T[]或者干脆统一成数组。教训这种一次性任务装库写脚本是过度设计。但要主动把坑告诉下游不然一个月后他还会来问你。场景三把 JSON 配置导给老 ERP公司内部配置中心存的是 JSON某个老 ERP 只吃 XML而且要求最外层必须是Service。我的做法是在导出层固定包一层payload{Service:load_config()}# 显式指定根节点名xml_stryq_dump(payload)# 或用 dicttoxml / XMLBuilder教训永远不要让工具去猜根节点名坑 4。显式声明输出才是可预期的。六、选型速查如果你符合以下情况直接用在线工具就行 只需要看一次结构、写文档举例 数据量小手动操作可接受 报文里没有属性、没有混合内容如果你符合以下情况请上脚本或解析库 XML 里带属性keyvalue 需要还原数字、布尔类型 同一个字段可能出现 1 次也可能出现 N 次 需要批量处理几十上百个文件如果你符合以下情况必须做正式的映射层 进生产链路有 SLA 有 XSD 或接口文档可以依赖 文件很大几百 MB 以上需要流式解析SAX / StAX 涉及金额、时间等精度敏感字段七、常见问题Q能用正则硬转吗A不能。XML 的嵌套、属性顺序、CDATA、实体转义、命名空间任何一条都能让正则崩掉。我见过最惨的案例是用正则处理报文上线三个月后发现某个客户的地址里带了个导致那三个月的数据全是脏的。Q为什么我转完 JSON 字段少了一半A九成是属性被丢了坑 1剩下一成是混合内容里的文本被丢了坑 5。Q为什么数字都带引号AXML 没有类型系统解析器只能按文本处理坑 2。需要在转换后自己做类型还原。Q在线工具贴公司数据安全吗A看实现。纯前端的工具转换在浏览器里完成数据不出本机这类可以放心用。需要上传到服务器处理的涉及客户信息、密钥、内部报文的一律别贴。判断方法开着 Network 面板点一次转换。Q几个 G 的大文件怎么办A别用 DOM 解析会一次性加载到内存。Java 用 StAXPython 用lxml.etree.iterparseNode 用sax流式处理。在线工具在这个量级完全不适用。QJSON 转 XML 再转回 JSON能还原吗A不能保证。至少类型会全部退化成字符串属性信息可能丢失单元素数组会塌缩成对象。转换是单向有损的别把它当序列化方案用。Q中文乱码怎么破A检查三处——XML 声明的encoding、文件实际编码、HTTP 响应头的charset。三者必须一致统一用 UTF-8 最省事。Q命名空间xmlns怎么处理A大多数轻量工具会直接忽略导致标签名带上ns1:这种前缀。xmltodict可以传process_namespacesTrueJackson 用JacksonXmlProperty(namespace ...)显式声明。八、总结JSON ↔ XML 转换这件事技术难度不高坑全在你以为它无损。把这几条记住能省下你后面无数次线上排查✅转换是有损的动手前先确认会丢什么✅XML 属性是头号杀手先看报文有没有keyvalue✅所有值默认是字符串类型还原是你的活不是工具的活✅单条 vs 多条决定对象还是数组下游一律按数组处理✅根节点名要显式声明别让工具猜✅一次性任务用在线工具生产链路用解析库别搞反⚠️ 特别提醒如果你的接口里有金额、时间戳、长整型 ID转换完之后务必做一次字段级比对。这类字段的精度和类型问题往往要到对账时才暴露那时候已经晚了。
企业数字化 ERP 产品动态
相关推荐
高级搜索引擎技巧揭秘:3个最佳实践让你零代码建站也能霸屏 高级搜索引擎技巧揭秘:3个最佳实践让你零代码建站也能霸屏 自己不会代码想做网站,却总被“SEO太难”劝退?别慌,这行干了十年,见过太多小白因不懂 高级搜索引擎技巧 而白扔广告费。其实, 最佳实践 从来不是背代码,而是用对工具、踩准节点。… · 2026/9/27 1:36:48
Fast-LIO2与LIO-SAM的IMU配置避坑指南:400Hz降频实测与调试流程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 1:36:48
图盲去模糊实战:从图构建、核估计到图神经网络训练与避坑 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 1:36:48
车辆-目标检测数据集 一、数据集简介
数据集信息介绍:共有 37850 张图像和一一对应的标注文件 标注文件格式提供了两种,包括VOC格式的xml文件和YOLO格式的txt文件。 标注的对象共有以下几种:
二、数据规模与标注信息
如何详细的看yolo格式的标准文件࿰… · 2026/9/27 2:12:02
5G互操作MML命令实战:参数配置与避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 2:11:38
随机森林分类实战:从决策树原理到sklearn调参避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 2:11:32
百度搜索不到任何网站免费工具推荐 网站被黑挂马搜不到?3个免费工具教你自查修复 你的网站昨晚还好好的,今早打开百度一搜,首页直接消失,或者点击进去是一片空白,甚至弹出奇怪的赌博广告链接。这种 网站被黑挂马不知道怎么办… · 2026/9/27 2:11:32
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01