反序列化时在嵌套元素中获取 null xml
Getting null in nested elements when deserializing xml
我正在将我的 xml 字符串反序列化为我的 classes。
问题是嵌套的子元素或其属性的一部分 return null.
这是我的反序列化函数:
public static T DeSerialize<T>(this string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StringReader(xml))
{
T result = (T)serializer.Deserialize(reader);
return result;
}
}
这是我的 classes:
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
private GameType[] typesField;
private Platform platformField;
private string memoField;
[System.Xml.Serialization.XmlArray("Types", Order = 0)]
[System.Xml.Serialization.XmlArrayItem("Data", IsNullable = false)]
public GameType[] Types
{
get
{
return this.typesField;
}
set
{
this.typesField= value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Platform", Order = 1)]
public Platform Platform
{
get
{
return this.platformField;
}
set
{
this.platformField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Memo
{
get
{
return this.memoField;
}
set
{
this.memoField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Platform
{
private decimal compressedField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public decimal Compressed
{
get
{
return this.compressedField;
}
set
{
this.compressedField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class GameType
{
private Code[] codeField;
private string nameField;
[System.Xml.Serialization.XmlArrayAttribute("Code", Order = 0)]
[System.Xml.Serialization.XmlArrayItemAttribute("Category", IsNullable = false)]
public Code[] Code
{
get
{
return this.codeField;
}
set
{
this.codeField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Name
{
get
{
return this.nameField;
}
set
{
this.nameField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Code
{
private string textField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Text
{
get
{
return this.textField;
}
set
{
this.textField= value;
}
}
}
这里是 xml:
<VideoGames Memo="1">
<Types>
<Data Name="RPG">
<Code>
<Category Text="TestingData"/>
</Code>
</Data>
</Types>
<Platform Compressed="3.2876"/>
</VideoGames>
我正在像这样使用反序列化:
string xml = "";//xml string above.
VideoGames a = xml.DeSerialize<VideoGames>();
我希望class中的每个属性都有值,但只有VideoGames中的Memo有值,其他都是空的。
例如:a.Types
为空,但a.Memo
为“1”。
我已经尝试了该主题搜索到的所有相关问题,并且 none 有效。
注:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
我已经检查了这个 xDoc,它加载完美,没有丢失任何东西。
诊断 XML 反序列化问题的最简单方法是 序列化为 XML 并将观察到的 XML 与所需的 XML。通常问题会立即显现出来。
如果我按如下方式创建并序列化 VideoGames
的实例:
var root = new VideoGames
{
Types = new []
{
new GameType
{
Name = "RPG",
Code = new []
{
new Code { Text = "TestingData" },
}
},
},
Platform = new Platform { Compressed = 3.2876m, },
};
var xml = root.GetXml(omitStandardNamespaces: true);
Console.WriteLine(xml);
使用以下扩展方法:
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
{
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
{
ns = new XmlSerializerNamespaces();
ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
}
using (var textWriter = new StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
则输出为:
<VideoGames>
<Types xmlns="http://www.specifiedcompany.com/API">
<Data Name="RPG">
<Code>
<Category Text="TestingData" />
</Code>
</Data>
</Types>
<Platform Compressed="3.2876" xmlns="http://www.specifiedcompany.com/API" />
</VideoGames>
演示 fiddle here.
如您所见,子元素 <Types>
和 <Platform>
都在 XML namespace 中序列化,具体来说 http://www.specifiedcompany.com/API
.
您的反序列化失败,因为在示例 XML 中,这些元素不在任何命名空间中。
为什么会这样?这是因为你所有的 类 包括 VideoGames
都有一个 XmlTypeAttribute
attribute applied that specifies a Namespace
:
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
}
这个属性的作用是指定默认情况下,该类型的所有属性都应该序列化到指定的命名空间。 (与 XmlRootAttribute
比较,后者指定如何序列化根元素 <VideoGames>
本身,而不仅仅是其子元素。)
如果您不想这样,请从您的 c# 类 VideoGames
、Platform
、GameType
和 [=27 中删除 XmlTypeAttribute.Namespace
设置=](演示 fiddle #2 here)。如果您确实需要,请修改您的 XML 以包含所需的命名空间,如此答案中的输出 XML 所示。
我正在将我的 xml 字符串反序列化为我的 classes。 问题是嵌套的子元素或其属性的一部分 return null.
这是我的反序列化函数:
public static T DeSerialize<T>(this string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StringReader(xml))
{
T result = (T)serializer.Deserialize(reader);
return result;
}
}
这是我的 classes:
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
private GameType[] typesField;
private Platform platformField;
private string memoField;
[System.Xml.Serialization.XmlArray("Types", Order = 0)]
[System.Xml.Serialization.XmlArrayItem("Data", IsNullable = false)]
public GameType[] Types
{
get
{
return this.typesField;
}
set
{
this.typesField= value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Platform", Order = 1)]
public Platform Platform
{
get
{
return this.platformField;
}
set
{
this.platformField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Memo
{
get
{
return this.memoField;
}
set
{
this.memoField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Platform
{
private decimal compressedField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public decimal Compressed
{
get
{
return this.compressedField;
}
set
{
this.compressedField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class GameType
{
private Code[] codeField;
private string nameField;
[System.Xml.Serialization.XmlArrayAttribute("Code", Order = 0)]
[System.Xml.Serialization.XmlArrayItemAttribute("Category", IsNullable = false)]
public Code[] Code
{
get
{
return this.codeField;
}
set
{
this.codeField= value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Name
{
get
{
return this.nameField;
}
set
{
this.nameField= value;
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.specifiedcompany.com/API")]
public partial class Code
{
private string textField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Text
{
get
{
return this.textField;
}
set
{
this.textField= value;
}
}
}
这里是 xml:
<VideoGames Memo="1">
<Types>
<Data Name="RPG">
<Code>
<Category Text="TestingData"/>
</Code>
</Data>
</Types>
<Platform Compressed="3.2876"/>
</VideoGames>
我正在像这样使用反序列化:
string xml = "";//xml string above.
VideoGames a = xml.DeSerialize<VideoGames>();
我希望class中的每个属性都有值,但只有VideoGames中的Memo有值,其他都是空的。
例如:a.Types
为空,但a.Memo
为“1”。
我已经尝试了该主题搜索到的所有相关问题,并且 none 有效。
注:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
我已经检查了这个 xDoc,它加载完美,没有丢失任何东西。
诊断 XML 反序列化问题的最简单方法是 序列化为 XML 并将观察到的 XML 与所需的 XML。通常问题会立即显现出来。
如果我按如下方式创建并序列化 VideoGames
的实例:
var root = new VideoGames
{
Types = new []
{
new GameType
{
Name = "RPG",
Code = new []
{
new Code { Text = "TestingData" },
}
},
},
Platform = new Platform { Compressed = 3.2876m, },
};
var xml = root.GetXml(omitStandardNamespaces: true);
Console.WriteLine(xml);
使用以下扩展方法:
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
{
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
{
ns = new XmlSerializerNamespaces();
ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
}
using (var textWriter = new StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
则输出为:
<VideoGames>
<Types xmlns="http://www.specifiedcompany.com/API">
<Data Name="RPG">
<Code>
<Category Text="TestingData" />
</Code>
</Data>
</Types>
<Platform Compressed="3.2876" xmlns="http://www.specifiedcompany.com/API" />
</VideoGames>
演示 fiddle here.
如您所见,子元素 <Types>
和 <Platform>
都在 XML namespace 中序列化,具体来说 http://www.specifiedcompany.com/API
.
您的反序列化失败,因为在示例 XML 中,这些元素不在任何命名空间中。
为什么会这样?这是因为你所有的 类 包括 VideoGames
都有一个 XmlTypeAttribute
attribute applied that specifies a Namespace
:
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.specifiedcompany.com/API")]
public partial class VideoGames
{
}
这个属性的作用是指定默认情况下,该类型的所有属性都应该序列化到指定的命名空间。 (与 XmlRootAttribute
比较,后者指定如何序列化根元素 <VideoGames>
本身,而不仅仅是其子元素。)
如果您不想这样,请从您的 c# 类 VideoGames
、Platform
、GameType
和 [=27 中删除 XmlTypeAttribute.Namespace
设置=](演示 fiddle #2 here)。如果您确实需要,请修改您的 XML 以包含所需的命名空间,如此答案中的输出 XML 所示。