C# 从XML数据反序列化数组(在ServiceStack中)
我得到了以下XML数据块:C# 从XML数据反序列化数组(在ServiceStack中),c#,xml-serialization,servicestack,C#,Xml Serialization,servicestack,我得到了以下XML数据块: <ArrayOfRESTDataSource xmlns="http://SwitchKing.Common/Entities/RESTSimplified/2010/07" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <RESTDataSource> <Description>MyTest</Description> <Enabled&
<ArrayOfRESTDataSource xmlns="http://SwitchKing.Common/Entities/RESTSimplified/2010/07" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<RESTDataSource>
<Description>MyTest</Description>
<Enabled>true</Enabled>
</RESTDataSource>
</ArrayOfRESTDataSource>
我从如下服务器读取上述XML数据:
WebRequest client = WebRequest.Create( "http://server:80/datasources" );
using( StreamReader sr = new StreamReader( client.GetResponse().GetResponseStream()) ) {
string xml = sr.ReadToEnd();
var response = ServiceStack.Text.XmlSerializer.DeserializeFromString<ArrayOfRESTDataSource>( xml );
}
更新2
解决方案在下面的@mythz答案中,但只是为了完整性/清晰性:我做错的是在我的DTO中添加了另一个级别-顶级类
ArrayFrestDataSource
实际上是一个以XML形式包含子项的类,因此它应该是一个集合类型。您可以使用[CollectionDataContract(…)]
要修改数组/集合的序列化输出,请参见此
调试序列化和集成问题
当试图解决像这样的集成问题时,第一步是隔离问题。i、 e.把其他的东西都拿走,只关注问题。e、 在本例中,我将只关注XML和DTO,并将它们与您的服务分离
只需在后台使用.NET的Xml DataContractSerializer,并且不添加任何额外的转换或字节开销(只是原始DTO按原样序列化),因此,如果您可以让它在您的服务之外工作,那么您可以将相同的DTO放回您的服务中,并且它也可以在线工作
方便的ServiceStack扩展方法
ServiceStack提供了方便的扩展方法来序列化/反序列化和分析数据模型:
序列化/反序列化扩展方法
将字符串打印到控制台string.Format()args(如果有)
您的序列化DTO是什么样子的
当您尝试创建DTO的形状时,应该做的第一步是填充并打印它们,以查看其外观。查看XML输出块,我提出了以下DTO:
[DataContract(Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07")]
public class RESTDataSource
{
[DataMember]
public bool Enabled { get; set; }
[DataMember]
public string Description { get; set; }
}
[CollectionDataContract(ItemName = "RESTDataSource", Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07")]
public class ArrayOfRESTDataSource : List<RESTDataSource>
{
public ArrayOfRESTDataSource() { }
public ArrayOfRESTDataSource(IEnumerable<RESTDataSource> collection) : base(collection) { }
}
它将打印到控制台:
<?xml version="1.0" encoding="utf-8"?><ArrayOfRESTDataSource xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://SwitchKing.Common/Entities/RESTSimplified/2010/07"><RESTDataSource><Description>MyTest</Description><Enabled>true</Enabled></RESTDataSource></ArrayOfRESTDataSource>
如果所有字段都填充了预期值,那么您就完成了,可以更新ServiceStack web服务DTO。为什么要填充数据?它在上面的XML块中的什么位置?您要说的是将数据重命名为RESTDataSource?尝试过之后,DataSource类会被实例化,但不会向集合中添加任何项。使用DTOs+更新过程以调试未来类似的序列化/集成问题。哇,我现在感觉太愚蠢了。当然,它应该是具有
CollectionDataContract
的顶级类,否则它与XML布局不匹配。谢谢你给mythz一个非常好的书面回答,我相信这些信息也会帮助其他人。
T.ToJson() / string.FromJson<T>() //Serialize JSON
T.ToJsv() / string.FromJsv<T>() //Serialize JSV
T.ToXml() / string.FromXml<T>() //Serialize XML
T.PrintDump()
string.Print(args)
[DataContract(Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07")]
public class RESTDataSource
{
[DataMember]
public bool Enabled { get; set; }
[DataMember]
public string Description { get; set; }
}
[CollectionDataContract(ItemName = "RESTDataSource", Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07")]
public class ArrayOfRESTDataSource : List<RESTDataSource>
{
public ArrayOfRESTDataSource() { }
public ArrayOfRESTDataSource(IEnumerable<RESTDataSource> collection) : base(collection) { }
}
var dto = new ArrayOfRESTDataSource {
new RESTDataSource { Enabled = true, Description = "MyTest" } };
dto.ToXml().Print();
<?xml version="1.0" encoding="utf-8"?><ArrayOfRESTDataSource xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://SwitchKing.Common/Entities/RESTSimplified/2010/07"><RESTDataSource><Description>MyTest</Description><Enabled>true</Enabled></RESTDataSource></ArrayOfRESTDataSource>
var dto = xml.FromXml<ArrayOfRESTDataSource>();
dto.PrintDump();
[
{
Enabled: True,
Description: MyTest
}
]