最稳方案是用XmlDocument加载XML后调用Newtonsoft.Json的JsonConvert.SerializeXmlNode(),它能正确处理命名空间、属性、文本节点等;切勿用InnerXml或XDocument手动映射,也别尝试System.Text.Json直接序列化XmlDocument。

用 XmlDocument + JsonConvert.SerializeXmlNode() 最稳
直接转 XML 到 JSON,别自己手写解析树。C# 生态里最可靠的是 Newtonsoft.Json 提供的 JsonConvert.SerializeXmlNode() ——它能处理命名空间、属性、文本节点、空元素等常见坑点。
常见错误现象:XmlDocument.Load() 后直接调 .InnerXml 再塞进 JsonConvert.SerializeObject(),结果只得到字符串字段,不是结构化 JSON;或者用 XDocument 转成 JObject 手动映射,一遇到 xmlns 就崩。
- 必须先加载为
XmlDocument(不是XDocument),否则SerializeXmlNode不认 - 如果 XML 有默认命名空间,得在加载前用
XmlNamespaceManager处理,否则属性和子节点可能丢 - 默认会把所有文本内容包进
#text字段,加参数XmlNodeConvertMode.IgnoreComments无用,得用JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true)的第三个参数omitRootObject = true来扁平化顶层
示例:
var doc = new XmlDocument();
doc.LoadXml("<root><item id='123'>hello</item></root>");
string json = JsonConvert.SerializeXmlNode(doc, Formatting.Indented, true);遇到带命名空间的 XML 怎么办
命名空间不是装饰,是解析器的硬性分隔符。没处理就调 SerializeXmlNode,大概率输出空对象或字段全 null。
使用场景:SOAP 响应、WCF 返回、某些政府接口的 XML 数据。
- 不能靠正则删
xmlns属性——会破坏 XML 合法性,XmlDocument.Load()可能直接抛XmlException - 正确做法:创建
XmlNameTable和XmlNamespaceManager,但更简单的是预处理——用XmlDocument加载后,遍历所有节点,用RemoveAll()清掉Attributes里的xmlns*,再调序列化 - 注意:清完 namespace 后,原 XML 的
xs:element这类前缀引用会失效,如果下游要校验 schema,这步就不能做
System.Text.Json 不支持直接 XML 转 JSON
别试 JsonSerializer.Serialize() 套 XElement 或 XmlDocument,它根本不识别这些类型,会报 NotSupportedException: Cannot serialize object of type XmlDocument。
性能 / 兼容性影响:有人想避开 Newtonsoft,改用微软原生库,但目前(.NET 6/7/8)System.Text.Json 没提供任何 XML 相关 API。硬要不用第三方,只能自己写 SAX 式解析器,成本远高于引入一个 NuGet 包。
-
Newtonsoft.Json仍是最小依赖、最成熟的选择,哪怕项目已用System.Text.Json做主序列化器,混用也完全没问题 - 若真要统一栈,可先用
XmlDocument解析,再手动映射到Dictionary<string object></string>或 record 类型,最后交由System.Text.Json序列化——但中间多一层对象转换,没明显收益
JSON 键名大小写和空值怎么控制
JsonConvert.SerializeXmlNode() 默认按 XML 原样输出节点名,不会自动 PascalCase → camelCase。null 值默认被忽略,但有时你需要显式保留 "id": null。
- 控制键名:没法直接改,得转完再用
JObject遍历重命名,或提前把XmlDocument的ChildNodes名称批量替换 - 保留 null:加
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include }传给SerializeXmlNode的重载方法(注意不是静态版,要用实例JsonSerializer.Create(settings)) - 空字符串
""和nil="true"属性(xsi:nil)是两回事,后者需额外检查XmlAttribute是否含xsi:nil="true",然后手动设为JValue.Null
这事没银弹。XML 结构越不规则,JSON 输出越难“好看”,别强求一步到位,先保数据完整,再按需清洗。


















