Per*_*Per 5 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>true</Enabled>
</RESTDataSource>
</ArrayOfRESTDataSource>
Run Code Online (Sandbox Code Playgroud)
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; }
}
Run Code Online (Sandbox Code Playgroud)
我从这样的服务器上读取了上面的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 );
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:我需要更改或装饰什么public RESTDataSource[] Data才能让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<RESTDataSource>
{
public DataSource() { }
public DataSource( IEnumerable<RESTDataSource> collection ) : base( collection ) { }
}
Run Code Online (Sandbox Code Playgroud)
更新2
解决方案在下面的@mythz答案中,但仅仅是为了完整性/清晰度:我做错了是在我的DTO中添加另一个级别 - 顶级类ArrayOfRESTDataSource是实际拥有XML中的子项的那个,所以它就是那个应该是一个集合类型.
您可以使用[CollectionDataContract(...)]修改数组/集合的序列化输出,请参阅前面的答案以获取示例.
尝试解决此类集成问题时,第一步是隔离问题.即删除其他所有内容,只关注问题.例如,在这种情况下,我只关注XML和DTO,并将它们与您的服务分离.
ServiceStack只是在底层使用.NET的Xml DataContractSerializer,并没有添加任何额外的转换或字节开销(它只是原始的DTO序列化),所以如果你能在服务之外工作,你可以放置相同的DTO回到你的服务,它也将通过电线工作.
ServiceStack提供了方便的扩展方法来序列化/反序列化和分析您的数据模型:
T.ToJson() / string.FromJson<T>() //Serialize JSON
T.ToJsv() / string.FromJsv<T>() //Serialize JSV
T.ToXml() / string.FromXml<T>() //Serialize XML
Run Code Online (Sandbox Code Playgroud)
以Pretty JSV转储格式递归打印对象图
T.PrintDump()
Run Code Online (Sandbox Code Playgroud)
将字符串打印到控制台解析string.Format() args(如果有)
string.Print(args)
Run Code Online (Sandbox Code Playgroud)
在尝试提出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) { }
}
Run Code Online (Sandbox Code Playgroud)
然后填充并转储它们:
var dto = new ArrayOfRESTDataSource {
new RESTDataSource { Enabled = true, Description = "MyTest" } };
dto.ToXml().Print();
Run Code Online (Sandbox Code Playgroud)
哪些打印到控制台:
<?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>
Run Code Online (Sandbox Code Playgroud)
这看起来像我们想要的.如果它没有调整上面的DTO,直到你获得与预期的XML相同的块.
当您具有与XML相同形状的DTO时,您可以开始尝试序列化它们:
var dto = xml.FromXml<ArrayOfRESTDataSource>();
dto.PrintDump();
Run Code Online (Sandbox Code Playgroud)
这将打印这个漂亮的对象图:
[
{
Enabled: True,
Description: MyTest
}
]
Run Code Online (Sandbox Code Playgroud)
如果所有字段都填充了预期值,那么您就完成了,并且可以更新ServiceStack Web服务DTO.