如何解决C# XmlSerializer DefaultAttribute 属性仍然为可空值序列化
我想减少序列化输出中的混乱,为经常使用或不使用的属性引入默认值。
但是,它们仍然在输出中。我做错了什么?
这应该是完整的(虽然没有编译):
[Serializable]
public class MyClass
{
[DefaultValue(null)]
public string Alias { get; set; } = null;
[DefaultValue(false)]
public bool Deactivated { get; set; } = false;
[DefaultValue(null)]
public bool? MyNullable { get; set; } = null;
}
public static string SerializefromObject<T>(this T toSerialize)
{
var xmlSerializer = new XmlSerializer(toSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter,toSerialize);
return textWriter.ToString();
}
}
var myClass = new MyClass();
var str = SerializefromObject(myClass);
<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyNullable xsi:nil="true" />
</MyClass>
如何去掉序列化xml中的nullable?
解决方法
Self 的回答很有帮助,但最后还是有一些问题,所以我没有遵循。稍后我将在此处概述它以供后代使用,以免在评论中或通过离线链接丢失。
我自己的解决方案:
使用标准的 .net xml 序列化,将序列化的字符串重新读取到 XElement 中,删除所有“nil”。然后再次 .ToString() 。
绝对是一个中等不错的解决方案,所以请随意想出更好的方法。
建议的条件序列化对我来说意味着太多额外的代码,我想避免。
我的解决方案还有一个缺点,即不能为可空值指定 DefaultValues,它们在为空时总是被省略。不过这对我来说很好。当我没有默认值时,我使用可空值。
/// <summary>
/// use for compact serializations
/// nullables that don't have a value are omitted (irrespecitve of DefaultValue!)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="toSerialize"></param>
/// <returns></returns>
public static string SerializeFromObject_NoNils<T>(T toSerialize)
{
var ele = Serialize<T>(toSerialize);
void removeNils(XNode node)
{
// recursion
if (node is XElement elem)
{
foreach (var child in elem.DescendantNodes())
removeNils(child);
//foreach (var child in elem.Descendants())
// removeNils(child);
}
// same level
while (node != null)
{
var nextnode = node.NextNode;
//if (node.)
if ((node as System.Xml.Linq.XElement)?.Attribute("{http://www.w3.org/2001/XMLSchema-instance}nil")?.Value == "true")
node.Remove();
node = nextnode;
}
}
removeNils(ele.FirstNode);
return ele.ToString();
}
如果有人想建立或改进 Self 的答案 - 这有一个缺点,即 DefaultValue 属性似乎不起作用(它似乎适用于 default(type) 而不是该属性),这里是从这里复制/粘贴的他的链接,添加了一个空命名空间,因为默认的 .net 反序列化会遇到 DataSerializerContract 命名空间。
所以,这不是我的代码,归功于用户 Self。
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Runtime.Serialization;
public class Program
{
public static void Main()
{
var myClass = new MyClass();
var str_dc = DataContract_SerializeFromObject(myClass);
str_dc.Dump();
var str_xml = SerializeFromObject(myClass);
str_xml.Dump();
}
public static string SerializeFromObject<T>( T toSerialize)
{
var xmlSerializer = new XmlSerializer(toSerialize.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter,toSerialize);
return textWriter.ToString();
}
}
public static string DataContract_SerializeFromObject<T>( T toSerialize)
{
var xmlSerializer = new DataContractSerializer(toSerialize.GetType());
using (var output = new StringWriter())
using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented })
{
xmlSerializer.WriteObject(writer,toSerialize);
return output.GetStringBuilder().ToString();
}
}
}
[DataContract(Namespace = "")] // default namespace is not deserializable with standard functionality
[Serializable]
public class MyClass
{
[DataMember(EmitDefaultValue = false)] [DefaultValue(null)]
public string Alias { get; set; } = null;
[DataMember(EmitDefaultValue = false)] [DefaultValue(false)]
public bool Deactivated { get; set; } = false;
[DataMember(EmitDefaultValue = false)] [DefaultValue(null)]
public bool? MyNullable { get; set; } = null;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。