如何让Json.NET将空XML元素序列化为空字符串

Jon*_*röm 3 c# json json.net

Json.NET 6.0 Release 3 的发行说明指出

更改 - 空白XML元素将写为空字符串而不是null

但这不是我的经历.

var xmlText = @"<document xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" Version=""1.1"">
                    <empty/>
                    <space> </space>
                    <null xsi:nil=""true""/>
                </document>";
var doc = new XmlDocument();
doc.LoadXml(xmlText);
var jsonText = JsonConvert.SerializeXmlNode(doc);
Run Code Online (Sandbox Code Playgroud)

我期望

"empty":"", "space":" ", "null":{"@xsi:nil":"true"}
Run Code Online (Sandbox Code Playgroud)

但得到了

"empty":null, "space":"", "null":{"@xsi:nil":"true"}
Run Code Online (Sandbox Code Playgroud)

丢失的空间现在不是问题,但我真的希望将空XML元素序列化为""而不是null.这可能吗?

Ili*_*mov 5

如果以下列格式编写xml,您将获得所需的内容:

var xmlText = @"<document xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" Version=""1.1"">
                <empty></empty>
                <space> </space>
                <null xsi:nil=""true""/>
            </document>";
Run Code Online (Sandbox Code Playgroud)

您可以注意到要将序列化为空字符串的节点写为<empty></empty>而不是<empty />.

问题在于JSON.NET用于将xml节点序列化为json,它使用XmlNodeConverter在其SerializeNode方法中检查类IsEmpty属性的XmlElement类.你可以阅读更多有关此属性在这里.上述方法的代码段决定是否null序列化空字符串,如下所示:

if (element.IsEmpty)
    writer.WriteNull();
else
    writer.WriteValue(string.Empty);
Run Code Online (Sandbox Code Playgroud)

当xml片段是自闭(<empty/>)时,该IsEmpty属性返回true,并且在json字符串中写入null,否则(<empty></empty>),它返回false并且在json字符串中写入string.empty.

更新1:

此更新应解决此处描述的问题.(该答案的评论中也提供了该链接).

为了能够序列化没有值的属性<empty></empty>而不是<empty/>,我们应该执行自定义xml序列化,因此Serializetest该类(在上面的链接中可用)应如下所示:

[Serializable]
public class Serializetest : IXmlSerializable
{
    public Serializetest()
    {
        Empty = string.Empty;
    }

    public string Empty { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement("Empty");
        writer.WriteValue(Empty);
        writer.WriteEndElement();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后主要方法:

var serializetest = new Serializetest();
string xmlText;

var serializer = new XmlSerializer(typeof(Serializetest));
using (var textWriter = new StringWriter())
{
    using (var xmlWriter = XmlWriter.Create(textWriter))
    {
        serializer.Serialize(xmlWriter, serializetest);
    }

    xmlText = textWriter.ToString();
}

var doc = new XmlDocument();
doc.LoadXml(xmlText);
var jsonText = JsonConvert.SerializeXmlNode(doc);

var json = JObject.Parse(jsonText);
var empty = (string)json.SelectToken("Serializetest.Empty");
// This should return empty string instead of null.
Run Code Online (Sandbox Code Playgroud)