从XML数据反序列化数组(在ServiceStack中)

我有以下大量的XML数据:

  MyTest true   

RESTDataSource可以发生0-n次。

这是我的课程:

 [DataContract( Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07" )] public class ArrayOfRESTDataSource { public RESTDataSource[] Data { set; get; } } [DataContract( Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07" )] public class RESTDataSource { [DataMember] public bool Enabled { get; set; } [DataMember] public string Description { get; set; } } 

我从这样的服务器上读取了上面的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( xml ); } 

我的问题是:我需要更改或装饰public RESTDataSource[] Data以获得对arrays工作的deseralization? 序列化单个RESTDataSource项工作正常,它只是我无法工作的数组。

提前致谢。

更新1

正如@mythz建议的那样,我将代码更新为此,但response.Data仍然为null。 我不明白的是什么?

 [DataContract( Namespace = "http://SwitchKing.Common/Entities/RESTSimplified/2010/07" )] public class ArrayOfRESTDataSource { [DataMember] public DataSource Data { set; get; } } [CollectionDataContract( ItemName = "RESTDataSource" )] public class DataSource : List { public DataSource() { } public DataSource( IEnumerable collection ) : base( collection ) { } } 

更新2

解决方案在下面的@mythz答案中,但仅仅是为了完整性/清晰度:我做错了是在我的DTO中添加另一个级别 – 顶级类ArrayOfRESTDataSource实际上是XML中的子项,所以它就是那个一个应该是集合类型的。

您可以使用[CollectionDataContract(...)]修改Arrays / Collections的序列化输出,请参阅前面的答案以获取示例 。

调试序列化和集成问题

尝试解决此类集成问题时的第一步是隔离问题。 即删除所有其他内容,只关注问题。 例如,在这种情况下,我只关注XML和DTO,并将它们与您的服务分离。

ServiceStack只是在底层使用.NET的Xml DataContractSerializer,并没有添加任何额外的转换或字节开销(它只是原始的DTO序列化),所以如果你能在服务之外工作,你可以放置相同的DTO回到你的服务,它也将通过电线工作。

方便的ServiceStack扩展方法

ServiceStack提供了方便的扩展方法来序列化/反序列化和分析您的数据模型:

序列化/反序列化扩展方法

 T.ToJson() / string.FromJson() //Serialize JSON T.ToJsv() / string.FromJsv() //Serialize JSV T.ToXml() / string.FromXml() //Serialize XML 

Handy Dump Utils

以Pretty JSV转储格式递归打印对象图

 T.PrintDump() 

将字符串打印到控制台解析string.Format() args(如果有)

 string.Print(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 { public ArrayOfRESTDataSource() { } public ArrayOfRESTDataSource(IEnumerable collection) : base(collection) { } } 

然后填充并转储它们:

 var dto = new ArrayOfRESTDataSource { new RESTDataSource { Enabled = true, Description = "MyTest" } }; dto.ToXml().Print(); 

哪个打印到控制台:

 MyTesttrue 

这看起来像我们想要的。 如果它没有调整上面的DTO,直到你获得与预期的XML相同的块。

当您具有与XML相同形状的DTO时,您可以开始尝试序列化它们:

 var dto = xml.FromXml(); dto.PrintDump(); 

这将打印这个漂亮的对象图:

 [ { Enabled: True, Description: MyTest } ] 

如果所有字段都填充了预期值,那么您就完成了,并且可以更新ServiceStack Web服务DTO。