Ali*_*kau 73 .net xml serialization nullable
我从第三方获得了一个xml,我需要将它反序列化为C#对象.此xml可能包含值为整数类型或空值的属性:attr ="11"或attr ="".我想将此属性值反序列化为类型为可空整数的属性.但XmlSerializer不支持反序列化为可空类型.在使用InvalidOperationException创建XmlSerializer期间,以下测试代码失败{"有一个错误反映了类型'TestConsoleApplication.SerializeMe'."}.
[XmlRoot("root")]
public class SerializeMe
{
[XmlElement("element")]
public Element Element { get; set; }
}
public class Element
{
[XmlAttribute("attr")]
public int? Value { get; set; }
}
class Program {
static void Main(string[] args) {
string xml = "<root><element attr=''>valE</element></root>";
var deserializer = new XmlSerializer(typeof(SerializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (SerializeMe)deserializer.Deserialize(xmlStream);
}
}
Run Code Online (Sandbox Code Playgroud)
当我将'Value'属性的类型更改为int时,反序列化失败并出现InvalidOperationException:
XML文档中存在错误(1,16).
任何人都可以建议如何将具有空值的属性反序列化为可空类型(作为null),同时将非空属性值反序列化为整数?有没有任何技巧,所以我不必手动对每个字段进行反序列化(实际上有很多)?
来自ahsteele的评论后更新:
据我所知,此属性仅适用于XmlElementAttribute - 此属性指定元素没有内容,无论是子元素还是正文.但我需要找到XmlAttributeAttribute的解决方案.无论如何我不能改变xml,因为我无法控制它.
仅当属性值为非空或缺少属性时,此属性才有效.当attr具有空值(attr ='')时,XmlSerializer构造函数失败(如预期的那样).
public class Element
{
[XmlAttribute("attr")]
public int Value { get; set; }
[XmlIgnore]
public bool ValueSpecified;
}
Run Code Online (Sandbox Code Playgroud)像Alex Scordellis这样的博客文章中的自定义Nullable类
我试图从这篇博文中采用这个课程来解决我的问题:
[XmlAttribute("attr")]
public NullableInt Value { get; set; }
Run Code Online (Sandbox Code Playgroud)
但是XmlSerializer构造函数因InvalidOperationException而失败:
无法序列化TestConsoleApplication.NullableInt类型的成员'Value'.
XmlAttribute/XmlText不能用于编码实现IXmlSerializable的类型}
丑陋的代理解决方案(我在这里写这段代码的耻辱:)):
public class Element
{
[XmlAttribute("attr")]
public string SetValue { get; set; }
public int? GetValue()
{
if ( string.IsNullOrEmpty(SetValue) || SetValue.Trim().Length <= 0 )
return null;
int result;
if (int.TryParse(SetValue, out result))
return result;
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
但我不想提出这样的解决方案,因为它打破了我的类的接口为其消费者.我最好手动实现IXmlSerializable接口.
目前看起来我必须为整个Element类实现IXmlSerializable(它很大)并且没有简单的解决方法......
小智 57
这应该工作:
[XmlIgnore]
public int? Age { get; set; }
[XmlElement("Age")]
public string AgeAsText
{
get { return (Age.HasValue) ? Age.ToString() : null; }
set { Age = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?); }
}
Run Code Online (Sandbox Code Playgroud)
Ali*_*kau 20
我通过实现IXmlSerializable接口解决了这个问题.我没有找到更简单的方法.
这是测试代码示例:
[XmlRoot("root")]
public class DeserializeMe {
[XmlArray("elements"), XmlArrayItem("element")]
public List<Element> Element { get; set; }
}
public class Element : IXmlSerializable {
public int? Value1 { get; private set; }
public float? Value2 { get; private set; }
public void ReadXml(XmlReader reader) {
string attr1 = reader.GetAttribute("attr");
string attr2 = reader.GetAttribute("attr2");
reader.Read();
Value1 = ConvertToNullable<int>(attr1);
Value2 = ConvertToNullable<float>(attr2);
}
private static T? ConvertToNullable<T>(string inputValue) where T : struct {
if ( string.IsNullOrEmpty(inputValue) || inputValue.Trim().Length == 0 ) {
return null;
}
try {
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
return (T)conv.ConvertFrom(inputValue);
}
catch ( NotSupportedException ) {
// The conversion cannot be performed
return null;
}
}
public XmlSchema GetSchema() { return null; }
public void WriteXml(XmlWriter writer) { throw new NotImplementedException(); }
}
class TestProgram {
public static void Main(string[] args) {
string xml = @"<root><elements><element attr='11' attr2='11.3'/><element attr='' attr2=''/></elements></root>";
XmlSerializer deserializer = new XmlSerializer(typeof(DeserializeMe));
Stream xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(xml));
var result = (DeserializeMe)deserializer.Deserialize(xmlStream);
}
}
Run Code Online (Sandbox Code Playgroud)
ahs*_*ele 11
我最近一直在搞乱序列化很多,并且在处理值类型的空数据时发现以下文章和帖子很有帮助.
如何在C#中使用XmlSerializer使值类型可以为空可以得到答案- 序列化详细介绍了XmlSerializer的一个非常好的技巧.具体来说,XmlSerialier查找XXXSpecified布尔属性以确定是否应该包含它以允许您忽略空值.
Alex Scordellis问StackOverflow问题得到了一个很好的答案.Alex也在他的博客上写了一篇关于他试图解决的问题的好文章.使用XmlSerializer反序列化为Nullable <int>.
有关Xsi:nil属性绑定支持的MSDN文档也很有用.与IXmlSerializable接口上的文档一样,尽管编写自己的实现应该是最后的选择.
| 归档时间: |
|
| 查看次数: |
56048 次 |
| 最近记录: |