JSON.. NET和替换XML中的@符号到JSON转换



JSON。. NET框架可以将XML转换为JSON,但它使用JSON中的@符号作为属性。我宁愿在将它发送给视图之前删除它。最好的方法是什么?

我知道我可以做一个直接的替换,但@字符可能是相关的地方,不应该被替换。这有正则表达式吗?

public ActionResult Layout()
{
    var xml = new XmlDocument();
    xml.XmlResolver = null;
    xml.Load(Server.MapPath("~/App_Data/Navigation.xml"));
    return Content(JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented));
}
{
  "Layout": {
    "Navigation": [
      {
        "@Type": "Menu",
        "@Title": "Dashboard"
      },
      {
        "@Type": "Menu",
        "@Route": "Events",
        "@Title": "Events",
        "Navigation": {
          "@Type": "Action",
          "@Route": "Event",
          "@Title": "+ Add Event",
          "@Order": "1",
          "Navigation": {
            "@Type": "Item",
            "@Route": "Event",
            "@Name": "Event",
            "Navigation": [
              {
                "@Route": "Pools",
                "@Type": "SubNavigation",
                "@Name": "Pools"
              },
              {
                "@Route": "Brackets",
                "@Type": "SubNavigation",
                "@Name": "Brackets"
              }
            ]
          }
        }
      }
    ]
  }
}

我花了很长时间才找到正确的答案,所以我想和大家分享一下:

var xDocument = XDocument.Parse("<xml><a attr="b">c</a></xml>");
var builder = new StringBuilder();
JsonSerializer.Create().Serialize(new CustomJsonWriter(new StringWriter(builder)), xDocument);
var serialized = builder.ToString();
public class CustomJsonWriter : JsonTextWriter
{
    public CustomJsonWriter(TextWriter writer): base(writer){}
    public override void WritePropertyName(string name)
    {
        if (name.StartsWith("@") || name.StartsWith("#"))
        {
            base.WritePropertyName(name.Substring(1));
        }
        else
        {
            base.WritePropertyName(name);
        }
    }
}
输出:

{"xml":{"a":{"attr":"b","text":"c"}}}

我使用了这个。如果有更好的方法,请告诉我。

public ActionResult Layout()
{
    var xml = new XmlDocument();
    xml.XmlResolver = null;
    xml.Load(Server.MapPath("~/App_Data/Navigation.xml"));
    var jsonText = JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented);
    return Content(Regex.Replace(jsonText, "(?<=")(@)(?!.*":\s )", string.Empty, RegexOptions.IgnoreCase));
}

Regex并不总是工作得很好,当内容有@字符时,首先,它也会被替换。所以我认为(?<!:)("@)(?!.":\s )可能更好。

另一个选择是从JsonConverter继承创建自己的OneWayXmlNodeConverter,并调用SerializeObject而不是SerializeXmlNode,像这样:

var json = JsonConvert.SerializeObject(xmlNode, new OneWayXmlNodeConverter());

我称之为"单向",因为我假设默认的XmlNodeConverter添加了"@"符号,因此它可以从结果JSON转换回XML。

如果您在项目中包含JSON.NET源代码(而不仅仅是编译库),创建OneWayXmlNodeConverter的简单方法是复制XmlNodeConverter代码,在私有GetPropertyName方法中删除硬编码的"@"符号,并将其保存为OneWayXmlNodeConverter

注意:我知道你的问题是特定于"替换"@"符号,但是这个问题的链接的预防变化被标记为重复。

已经有一段时间没有回复了,但这可能仍然对某人有所帮助。因为已经有了XMLDocument,所以可以在序列化它之前删除和转换属性。我尝试删除属性或将它们转换为元素。

public static void RemoveAllAttributes(XmlDocument xmlDocument)
{
     if (xmlDocument == null || !xmlDocument.HasChildNodes) return;
     foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes))
     {
          xmlElement.Attributes.RemoveAll();
     }
}
public static void ElementifyAllAttributes(XmlDocument xmlDocument)
{
    if (xmlDocument == null || !xmlDocument.HasChildNodes) return;
    foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes))
    {
        foreach (XmlAttribute xmlAttribute in xmlElement.Attributes)
        {
            xmlElement.AppendChild(xmlDocument.CreateElement(xmlAttribute.Name)).InnerText = xmlAttribute.Value;
        }
        xmlElement.Attributes.RemoveAll();
     }
}

然后;

private static string XmlToJson(XmlDocument xmlDocument)
{
    if (xmlDocument == null) return null;
    //Remove xml declaration
    xmlDocument.RemoveChild(xmlDocument.FirstChild);
    //Convert attributes to elements
    ElementifyAllAttributes(xmlDocument);
    return JsonConvert.SerializeXmlNode(xmlDocument, Formatting.None, false);
}

如果由于'@'符号而想要访问属性的值,请执行以下操作:

Navigation["@Type"]

这是我的regex贡献,使用前向和后向来确保它只发生在属性字段

(?m)(?<=^s+")(@)(?=.+":)

击穿:

(?m) -以多行模式运行

(?<=^s+") -向后查找行开头,一个或多个空格和引号

(@) -匹配引号后面的@

(?=.+":) -向前查找匹配任何字符至少一次,后面跟着另一个引号,然后是冒号

我建议使用以下regex,它与@ yiieio提供的相同,但增强使内容保持原样而不做任何修改,并且只影响属性名称

var jString = Regex.Replace(
JsonConvert.SerializeXmlNode(content, Newtonsoft.Json.Formatting.None, true),
 "(?<=(\,\"|\{\"))(@)(?!.*\":\\s )", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);

如果JSON是缩进的,这可以工作:

Regex.Replace(result, @"(s*)""@(.*)"":", @"$1""$2"":", RegexOptions.IgnoreCase);

首先用一些占位符替换xml内容中的所有"@"(例如{{at_the_rate}})。然后使用下面的代码

JsonConvert.SerializeXmlNode(doc).Replace("@", "").Replace("{{at_the_rate}}", "@")

相关内容

  • 没有找到相关文章

最新更新