c# - Newtonsoft.Json DeserializeXmlNode 将标签名称从数字更改为 "something"

标签 c# json .net xml json.net

我们有一个长期存在的应用程序,它使用一些曾经是 xml 的提要,但已转换为 json... 当然,我们“懒”地将解析器从读取 XmlDocument 更改为读取 JObject 或其他,因此我们使用“DeserializeXmlNode”从 json txt 转换为 XmlDocument。 很长一段时间一切都很好...直到我们从 Newtonsoft.Json 版本 4.5 和 6.0 更新到版本 12.0.x,突然我们开始遇到一些问题...

假设 json 看起来像这样:

{"version":"2.0","result":[{"mainobid":"123","typeId":"2","subobjects":{"1":{"data":"data"},"2":{"data":"data"}}}]}

我们过去得到的是 xml

<1><data>data</data></1><2><data>data</data></2>

标签

现在...而不是 <1> 标签,我们得到类似 <x0031> 的内容 不是 10,而是 _x0031_0 不是 45,而是 0x0034_5 而不是 100 _x0031_00

我可以把它关掉吗?或者我现在被迫改变解析来解码那个病态的x003....东西?

INB4 1:我意识到拥有 1: 和 <1> 并不是任何理智的人都希望拥有的东西,但我无法改变这一点,它是外部提要

INB4 2:我知道我们应该将解析从 xml 更改为 json,但如上所述 - 一些懒惰和重新使用 100% 正常工作的旧代码。

编辑:

private static void TestOldNewton()
{
    var jsonstr = "{\"version\":\"2.0\",\"result\":[{\"mainobid\":\"123\",\"typeId\":\"2\",\"subobjects\":{\"1\":{\"data\":\"data\"},\"2\":{\"data\":\"data\"}}}]}";
    var doc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonstr, "data");
    Console.WriteLine(doc.OuterXml);
    Console.ReadKey();
}

使用packages.config,例如:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Newtonsoft.Json" version="6.0.1" targetFramework="net48" />
</packages>

并接收输出:

<data><version>2.0</version><result><mainobid>123</mainobid><typeId>2</typeId><subobjects><1><data>data</data></1><2><data>data</data></2></subobjects></result></data>

新编译并在新的测试项目上运行。

最佳答案

更改的原因是以下 checkin : Fixed converting JSON to XML with invalid XML name characters 到 Json.NET 8.0.1 。此 checkin 添加了(除其他更改外)对 XmlConvert.EncodeName() 的调用里面 XmlNodeConverter.CreateElement() :

private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager)
{
    string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName);
    string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);

   IXmlElement element = (!StringUtils.IsNullOrEmpty(ns)) ? document.CreateElement(encodeName, ns) : document.CreateElement(encodeName);

    return element;
}

这是对 [add] support for converting JSON to XML with invalid XML name characters 进行的。这在这里适用,因为元素名称以数字开头,例如 <1>不是格式良好的 XML 元素名称,如 XML tagname starting with number is not working 中所述。 。事实上,严格来说,您之前生成的 XML 并不是格式良好的 XML。

正如您从上面的代码摘录中看到的,似乎没有办法禁用此更改并创建元素名称而不对其进行编码。

作为解决方法,因为您想要创建具有数字名称的元素,如 <1>无论如何,你可以子类 XmlTextWriter 并通过调用 XmlConvert.DecodeName() 解码名称。

This method does the reverse of the EncodeName(String) and EncodeLocalName(String) methods.

首先定义以下类:

public class NameEditingXmlTextWriter : XmlTextWriter
{
    readonly Func<string, string, string> nameEditor;

    public NameEditingXmlTextWriter(TextWriter writer, Func<string, string, string> nameEditor)
        : base(writer)
    {
        this.nameEditor = nameEditor;
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        var newLocalName = nameEditor(localName, ns);
        base.WriteStartElement(prefix, newLocalName, ns);
    }
}

然后按如下方式使用:

var doc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonstr, "root");

var sb = new StringBuilder();
using (var textWriter = new StringWriter(sb))
using (var writer = new NameEditingXmlTextWriter(textWriter, (n, ns) => XmlConvert.DecodeName(n)))
{
    doc.WriteTo(writer);
}
var outerXml = sb.ToString();

注释:

  • 您必须对已弃用的 XmlTextWriter 进行子类化而不是其替代品 XmlWriter 因为XmlWriter尝试写入格式错误的 XML 元素名称(如 <1>)时将引发异常.

  • 作为替代方案,因为 Json.NET 目前已根据 MIT License 获得许可。 ,您可以 fork 自己的 XmlNodeConverter 版本并删除对 XmlConvert.EncodeName() 的调用来自CreateElement() 。然而,这个解决方案似乎不太理想,因为它创建了维护要求,以使您的 fork 版本与 Newtonsoft 的版本保持同步。

演示 fiddle here .

关于c# - Newtonsoft.Json DeserializeXmlNode 将标签名称从数字更改为 "something",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64016941/

相关文章:

.net - wcf tcp async streamed 是可能的吗?

c# - 无法选择 ListView 项目两次

c# - 使用 Owinhost.exe 运行 OWIN Web 服务或控制台应用程序有什么区别

java - JsonNode isTextual() 莫名其妙地返回 false

c# - JSON 序列化程序写入过多 ']'

ios - 找不到适用于 iOS 的 stig -JSON dmg 文件

c# - 可空类型到底什么时候抛出异常?

c# - 在 MVC3 问题中键入安全的 URL 操作

c# - 如何读取设备和驱动程序版本

c# - skydrive System.Dynamic.DynamicObject