如何在 C# 中使用添加的自定义标签将 JSON 转换为 XML

Posted

技术标签:

【中文标题】如何在 C# 中使用添加的自定义标签将 JSON 转换为 XML【英文标题】:How to convert JSON to XML with added custom tag in C# 【发布时间】:2021-11-10 10:40:13 【问题描述】:

我有一些这种格式的 JSON 示例:


    "id": "532-513jg-5ujkl-5jiklf",
    "externalGuid": "93804jlkfes",
    "tagNumber": "2KMA",
    "project": 
        "id": "532kg-fw13jg-553klal-5jiklf",
        "projectName": "Test",
        "projectId": "1"
    ,
    "properties": [
        
            "id": "jkl39-jkl39084-agd208-hh82a9",
            "name": "Weight",
            "value": "1000",
            "statusCode": 
                "name": "Accepted",
                "code": 1
            
        ,
        
            "id": "jkl39-jkl384-123208-hh82a9",
            "name": "Length",
            "value": "10",
            "statusCode": 
                "name": "Not Accepted",
                "code": 3
            
        
    ]

我想将其转换为 XML,因此我执行以下操作: XmlDocument node = JsonConvert.DeserializeXmlNode(jsonString, "tag"); 这给了我以下 XML:

<tag>
  <id>532-513jg-5ujkl-5jiklf</id>
  <externalGuid>93804jlkfes</comosUID>
  <tagNumber>2KMA</tagNumber>
  <project>
    <id>532kg-fw13jg-553klal-5jiklf</id>
    <projectName>Test</projectName>
    <projectId>1</projectId>
  </project>
  <properties>
    <id>jkl39-jkl39084-agd208-hh82a9</id>
    <name>Weight</name>
    <value>1000</value>
    <statusCode>
      <name>Accepted</name>
      <code>1</code>
    </statusCode>
  <properties>
    <id>jkl39-jkl384-123208-hh82a9</id>
    <name>Length</name>
    <value>10</value>
    <statusCode>
      <name>Not Accepted</name>
      <code>3</code>
    </statusCode>
  </properties>
</tag>

这几乎是我想要的。然而,将要导入 XML 的系统需要一种稍微不同的格式。它希望每个属性都以&lt;property&gt; 标记开始和结束。所以属性数组看起来像这样:

<properties>
  <property>
    <id>jkl39-jkl39084-agd208-hh82a9</id>
    <name>Weight</name>
    <value>1000</value>
    <statusCode>
      <name>Accepted</name>
      <code>1</code>
    </statusCode>
  </property>
  <property>
    <id>jkl39-jkl384-123208-hh82a9</id>
    <name>Length</name>
    <value>10</value>
    <statusCode>
      <name>Not Accepted</name>
      <code>3</code>
    </statusCode>
  </property>
</properties>

如何使 XML 匹配此模板?也就是说,将properties标签替换为property,并将所有property标签包装在一个properties父标签中。

【问题讨论】:

【参考方案1】:

要更改输入格式,您应该首先将 JSON 反序列化为匹配模型,然后您可以使用 System.Xml.Linq 按您想要的顺序和结构导出节点。

Model model = JsonConvert.DeserializeObject<model>(jsonString);
var xml = new XElement("properties", 
               new XElement("property",
                  new XElement("id", model.Id),
                  new XElement("name", model.Name) /*and so on*/));

看起来要写很多东西,但实际上你可以用 XML 做任何你想做的事情。您可以准备方法来处理模型并对其进行调整,但这取决于您的要求。

您还可以创建另一个结构与 xml 文件对应的模型,然后您必须使用原始节点中的数据填充该模型,但这看起来像是很多不必要的工作。我个人会使用 System.Xml.Linq 来完成这样的任务。

【讨论】:

【参考方案2】:

您可以编写一个自定义 XmlNodeConverter,如果当前元素是一个数组,它将插入一个父元素。例如,

public class ArrayXmlNodeConverter : XmlNodeConverter

    public readonly string _arrayRootName;

    public ArrayXmlNodeConverter(string rootElement,string arrayRootName)
    
        (DeserializeRootElementName,_arrayRootName) = (rootElement,arrayRootName);
    
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        var token = JObject.Load(reader);
        ChangeArrayElementRoot(token);
        reader = token.CreateReader();
        reader.Read();
        return base.ReadJson(reader, objectType, existingValue, serializer);
    

    private void ChangeArrayElementRoot(JToken token)
    
        if (token.Type == JTokenType.Array)
        
            var arrayHolder = new JObject   _arrayRootName, token  ;
            token.Replace(arrayHolder);
        
        else
        
            foreach (var childToken in token)
            
                ChangeArrayElementRoot(childToken);
            
        
    

现在你可以使用 as

var xml = (XmlDocument)JsonConvert.DeserializeObject(jsonString,
                   typeof(XmlDocument), 
                   new ArrayXmlNodeConverter("tag","Property"));

Demo Code

【讨论】:

【参考方案3】:

这就是我解决它的方法。首先,我为相应的 JSON/XML 元素创建了 C# 类:

    [XmlRoot("tag")]
    [JsonObject(Title = "tag")]
    public class Tag
    
        [XmlElement("id")] public string Id  get; set; 
        [XmlElement("externalGuid")] public string ExternalGuid get; set; 
        [XmlElement("tagNumber")] public string TagNumber  get; set; 
        [XmlElement("project")] public Project Project  get; set; 
        [XmlArray("properties")] public List<Property> Properties  get; set; 
    

    [XmlType("property")]
    public class Property
    
        [XmlElement("id")] public string Id  get; set; 
        [XmlElement("name")] public string Name  get; set; 
        [XmlElement("value")] public string Value  get; set; 
        [XmlElement("status")] public Status Status  get; set; 
    

    public class Status
    
        [XmlElement("id")] public string Id  get; set; 
        [XmlElement("name")] public string Name  get; set; 
        [XmlElement("code")] public int Code  get; set; 
    

    public class Project
    
        [XmlElement("id")] public string Id  get; set; 
        [XmlElement("projectName")] public string ProjectName  get; set; 
        [XmlElement("projectId")] public string ProjectId  get; set; 
    

然后我实现了一个自定义的 Json 到 XML 转换器:

        public static string TransformJsonToXml<T>(string json)
        
            var jsonObjectAttribute = typeof(T).GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
            JObject root = JObject.Parse(json);
            var data = root[jsonObjectAttribute.Title];

            var obj = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(data));

            var serializer = new XmlSerializer(typeof(T));
            var stringWriter = new StringWriter();
            using var xmlWriter = XmlWriter.Create(stringWriter);
            var xmlSerializerNamespaces = new XmlSerializerNamespaces();
            xmlSerializerNamespaces.Add("","");
            serializer.Serialize(xmlWriter, obj, xmlSerializerNamespaces);
            return stringWriter.ToString();
        

现在将 JSON 转换为 XML 很简单: var xml = TransformJsonToXml&lt;Tag&gt;(jsonInput);

【讨论】:

以上是关于如何在 C# 中使用添加的自定义标签将 JSON 转换为 XML的主要内容,如果未能解决你的问题,请参考以下文章

如何将现有的 JSF 组件添加到我自己的自定义组件中?

如何将多个键值条目的 JSON 对象反序列化为 Rust 中的自定义结构

我的 Joomla 模板正在使用 JS 加载我的自定义 CSS。有没有办法将唯一版本标签添加到我的自定义 CSS 中?即:custom.css?20180101

如何读取android中xmpp消息标签中添加的自定义属性?

Django:如何查看已定义的自定义标签?

如何使用标签或标识符将多张图片添加到自定义 tableviewcells