繁体   English   中英

通过自定义更改将XML解析为JSON

[英]Parse an XML to JSON with custom changes

我有一段代码生成“模板”文件的XML库,所有数据都是根据当前用户动态地从项目中获取的。

我需要做的是将JSON结构字符串发送到API(我无法控制)。

我面临的问题是我无法使用JsonConvert.SerializeObject从XML生成这样的JSON(格式正确)。

借助于在线工具,我从JSON创建了此XMLJsonConvert.SerializeObject(XML)生成了一个JSON,但是例如代表一个数组项的element -我需要每个项都在[]RootDTO根元素,我根本不需要它。

因此,我需要完成的就是将XML转换为结构类似于JSON的JSON

使用“ json.net”可以吗? 我是否需要编写“自定义Serilizer”


我有的XML:

<?xml version="1.0" encoding="UTF-8"?>
<RootDTO>
   <destination>
      <name>companyName</name>
   </destination>
   <orderData>
      <amount>123.45</amount>     
      <items>
         <element>            
            <binding>saddle</binding>
            <components>
               <element>                            
                  <width>210</width>
               </element>
            </components>
            <description>Introductory x</description>         
         </element>
      </items>
   </orderData>
</RootDTO>

JSON JsonConvert.SerializeObject产生

{
   "?xml": {
      "@version": "1.0",
      "@encoding": "UTF-8"
   },
   "RootDTO": {
      "destination": {
         "name": "companyName"
      },
      "orderData": {
         "amount": "123.45",
         "items": {
            "element": {
               "binding": "saddle",
               "components": {
                  "element": {
                     "width": "210"
                  }
               },
               "description": "Introductory x"
            }
         }
      }
   }
} 

所需的JSON

{
   "destination": {
     "name": "companyName"
   },
   "orderData": {
      "amount": "123.45",
      "items": [
         {
            "binding": "saddle",
            "components": [
               {
                 "width": "210"
               }
            ],
            "description": "Introductory x"
         }
      ]
   }
}

您有以下问题:

  1. 您不需要根元素。

    可以轻松删除它,使用JsonConvert.SerializeXNode Method(XObject, Formatting, omitRootObject = true)或设置XmlNodeConverter.OmitRootObject = true

  2. 元素不会作为JSON数组返回。

    XML和JSON之间存在基本的不一致之处,因为XML没有数组的概念。 它仅包含具有名称的元素序列。 那么,Json.NET在什么情况下会创建数组? 在JSON和XML之间转换

    在同一级别上具有相同名称的多个节点被分组到一个数组中。

    但是,您有一个两级列表,如下所示:

     <Container> <element> </element> <!-- Repeat as necessary --> </Container> 

    Json.NET不会自动将容器元素识别为数组,因此您需要使用LINQ to XML预处理XML或使用LINQ to JSON进行后期处理。 我认为后者更容易。 幸运的是,所有列表条目都被命名为element从而使后处理变得简单明了。 可以使用以下两种扩展方法来完成:

     public static class JsonExtensions { public static JObject ToJObject(this XDocument xDoc) { // Convert to Linq to XML JObject var settings = new JsonSerializerSettings { Converters = new[] { new XmlNodeConverter { OmitRootObject = true } } }; var root = JObject.FromObject(xDoc, JsonSerializer.CreateDefault(settings)); // Convert two-level lists with "element" nodes to arrays. var groups = root.Descendants() .OfType<JProperty>() .Where(p => p.Name == "element") .GroupBy(p => (JObject)p.Parent) .Where(g => g.Key.Parent != null && g.Key.Properties().Count() == g.Count()) .ToList(); foreach (var g in groups) { // Remove values from properties to prevent cloning var values = g.Select(p => p.Value) .SelectMany(v => v.Type == JTokenType.Array ? v.Children().AsEnumerable() : new[] { v }) .ToList() .Select(v => v.RemoveFromLowestPossibleParent()); g.Key.Replace(new JArray(values)); } return root; } public static JToken RemoveFromLowestPossibleParent(this JToken node) { if (node == null) throw new ArgumentNullException("node"); var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault(); if (contained != null) contained.Remove(); // Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should if (node.Parent is JProperty) ((JProperty)node.Parent).Value = null; return node; } } 

    然后做:

      var xDoc = XDocument.Parse(xmlString); var root = xDoc.ToJObject(); var jsonString = root.ToString(); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM