使用 Json.NET (Newtonsoft) 将空数组从 JSON 转换为 XML

Posted

技术标签:

【中文标题】使用 Json.NET (Newtonsoft) 将空数组从 JSON 转换为 XML【英文标题】:Convert empty arrays from JSON to XML with Json.NET (Newtonsoft) 【发布时间】:2021-03-16 02:29:06 【问题描述】:

鉴于以下 JSON:

string json = @"
  
    ""Identifier"": ""MyID"",
    ""Data"": []
  ";

如果我使用XDocument xDocument = JsonConvert.DeserializeXNode(json, "Foo"); 将其转换为 XML,则生成的 XML 为:

  <Foo>
    <Identifier>MyID</Identifier>
  </Foo>

我想要的输出是这样的:

  <Foo>
    <Identifier>MyID</Identifier>
    <Data/>
  </Foo>

是否有序列化程序设置或我可以用来进行此更改的东西?

编辑:为清楚起见 - 我正在寻找一个通用的解决方案,但不提前知道 JSON 的结构。目标是简单地将任意 JSON 转换为 XML,而不会省略空数组的标签。

【问题讨论】:

【参考方案1】:

我认为这 issue 将是您看到的行为的原因。似乎归结为 xml 如何表示数组:节点只是重复

void Main()

    JsonConvert.DeserializeXNode(@" ""Identifier"": ""MyID"", ""Data"": [1,2,3]", "Foo", true, false);
    /*
        <Foo>
          <Identifier>MyID</Identifier>
          <Data>1</Data>
          <Data>2</Data>
          <Data>3</Data>
        </Foo>
    */
    JsonConvert.DeserializeXNode(@" ""Identifier"": ""MyID"", ""Data"": [null]", "Foo", true, false); // this seems to be the closest to what you are after, but it is semantically different from empty array
    /*
    <Foo>
      <Identifier>MyID</Identifier>
      <Data json:Array="true" xmlns:json="http://james.newtonking.com/projects/json" />
    </Foo>
    */
    JsonConvert.DeserializeXNode(@" ""Identifier"": ""MyID"", ""Data"": []", "Foo", true, false);
    /*
    <Foo>
      <Identifier>MyID</Identifier>
    </Foo>
    */

【讨论】:

【参考方案2】:

以下示例假设您有一个名为 Form1 (Form1.cs) 的表单。

尝试以下方法:

安装 Newtonsoft NuGet 包

在菜单上,查看 选择解决方案资源管理器 在解决方案资源管理器中,右键单击 选择管理 NuGet 包... 点击浏览 搜索:Newtonsoft.Json 点击Newtonsoft.Json 点击安装

创建一个名为 Foo 的类

Foo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace NewtonsoftEmptyXmlElement

    [XmlRoot(ElementName = "Foo")]
    public class Foo
    
        [XmlElementAttribute(ElementName = "Identifier")]
        public string Identifier  get; set; 

        [XmlArrayAttribute("Data")]
        public List<string> Data  get; set;  = new List<string>();
    

Form1.cs

添加以下 using 语句:

using Newtonsoft.Json;
using System.Xml;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;

GenerateXml(将 XML 作为字符串返回)

public static string GenerateXml<T>(object obj, System.Text.Encoding encoding)

    string xml = string.Empty;

    using (MemoryStream ms = new MemoryStream())
    
        XmlSerializer serializer = new XmlSerializer(typeof(T));

        //eliminate "xsd" and "xsi" namespaces
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");

        //indent Xml and eliminate Xml declaration
        XmlWriterSettings writerSettings = new XmlWriterSettings();
        writerSettings.OmitXmlDeclaration = true;
        writerSettings.Encoding = encoding;
        writerSettings.Indent = true;


        //create instance of XmlWriter
        XmlWriter writer = XmlWriter.Create(ms, writerSettings);

        serializer.Serialize(writer, (T)obj, ns);
       
        xml = encoding.GetString(ms.ToArray());

    

    return xml;

WriteXML(将 XML 写入文件)

public static void WriteXml<T>(object obj, string filename, System.Text.Encoding encoding)

    string xml = string.Empty;

    try
    
        using (StreamWriter fs = new StreamWriter(filename))
        
            XmlSerializer serializer = new XmlSerializer(typeof(T));

            //eliminate "xsd" and "xsi" namespaces
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("", "");

            //indent Xml and eliminate Xml declaration
            XmlWriterSettings writerSettings = new XmlWriterSettings();
            writerSettings.OmitXmlDeclaration = true;
            writerSettings.Encoding = encoding;
            writerSettings.Indent = true;


            //create instance of XmlWriter
            XmlWriter writer = XmlWriter.Create(fs, writerSettings);

            serializer.Serialize(writer, (T)obj, ns);

        
    
    catch(Exception ex)
    
        System.Diagnostics.Debug.WriteLine("Error: - " + ex.Message);
    
    

测试

private void Test()

    string json = @"
    
        ""Identifier"": ""MyID"",
        ""Data"": []
    ";

    //System.Diagnostics.Debug.WriteLine(json);
    Foo foo2 = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(json, new JsonSerializerSettings  NullValueHandling = NullValueHandling.Include );

    //Option 1 - get XML
    string xmlDoc = GenerateXml<Foo>(foo2, System.Text.Encoding.UTF8); 
    System.Diagnostics.Debug.WriteLine("\n\n" + xmlDoc);

    //Option 2 - write XML to file
    WriteXml<Foo>(foo2, @"C:\Temp\foo.xml", System.Text.Encoding.UTF8);

使用方法:

Test();

输出:

<Foo>
  <Identifier>MyID</Identifier>
  <Data />
</Foo>

【讨论】:

请查看已编辑的问题。这个解决方案需要我为 JSON 创建一个类。

以上是关于使用 Json.NET (Newtonsoft) 将空数组从 JSON 转换为 XML的主要内容,如果未能解决你的问题,请参考以下文章

.NET(C#) Json.Net(newtonsoft)使用LINQ查询JSON数据

.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json反序列化json示例教程

如何使用 NewtonSoft Json.Net 将 Json 字典反序列化为平面类

Newtonsoft.Json(Json.Net)学习笔记

Json.NET 与 Newtonsoft.Json SerializationBinder 不同

如何使用与 NewtonSoft (JSON.Net) 组件中的 JSON 匹配的 Swift 类从/向 JSON 读取/写入对象数组?