从XML数据反序列化阵列(在ServiceStack) [英] Deserializing array from XML data (in ServiceStack)

查看:142
本文介绍了从XML数据反序列化阵列(在ServiceStack)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有XML数据的以下块:

 < ArrayOfRESTDataSource的xmlns =HTTP:// SwitchKing。通用/实体/ RESTSimplified / 2010/07的xmlns:I =http://www.w3.org/2001/XMLSchema-instance> 
< RESTDataSource>
<说明与GT; MyTest的< /说明>
<&启用GT;真< /启用>
< / RESTDataSource>
< / ArrayOfRESTDataSource>



RESTDataSource 可出现0-n次。



和这里是我的类:

  [DataContract(命名空间= HTTP://SwitchKing.Common/Entities/RESTSimplified/2010/07)] 
公共类ArrayOfRESTDataSource
{
公共RESTDataSource [] {数据集;得到; }
}


[DataContract(命名空间=HTTP://SwitchKing.Common/Entities/RESTSimplified/2010/07)]
公共类RESTDataSource
{
[数据成员]
公共BOOL启用{搞定;组; }
[数据成员]
公共字符串描述{搞定;组; }
}



我是从这样的服务器读取上面的XML数据:

  WebRequest的客户端= WebRequest.Create(HTTP://服务器:80 /数据源); 
使用(StreamReader的SR =新的StreamReader(client.GetResponse()GetResponseStream())){
串XML = sr.ReadToEnd();
变种响应= ServiceStack.Text.XmlSerializer.DeserializeFromString&所述; ArrayOfRESTDataSource>(XML);
}



我的问题是:我需要做什么改变或装饰公共RESTDataSource []数据想要得到deseralization为阵列的工作?序列化单RESTDataSource项目工作得很好,它只是数组,我不能去上班。



在此先感谢。



更新1



由于@mythz的建议,我更新了我的代码,这一点,但response.Data仍然是空。 ?我怎么不明白

  [DataContract(命名空间=HTTP://SwitchKing.Common/Entities/RESTSimplified/2010/ 07)] 
公共类ArrayOfRESTDataSource
{
[数据成员]
公共数据源的数据{设定;得到; }
}

[CollectionDataContract(ITEMNAME =RESTDataSource)]
公共类数据源:列出< RESTDataSource>
{
公共数据源(){}
公共数据源(IEnumerable的< RESTDataSource>收集):基地(集合){}
}

更新2



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


解决方案

您可以使用 [ CollectionDataContract(...)] 来修改阵列/收藏序列化输出,看到的为例以前的答案。



调试序列化和集成问题



试图解决集成问题像这样的隔离问题时的第一步。即去掉一切路程,只专注于这个问题。例如在这种情况下,我只想专注于XML和的DTO,并从你的服务去耦。



ServiceStack 只使用.NET的XML DataContractSerializer的引擎盖下,并不会增加任何额外的转换或字节的开销(这只是原始的DTO序列化为-IS),所以如果你能得到它的工作您的服务之外,你可以把相同的DTO回你的服务,它也将通过线路工作。



手持ServiceStack扩展方法



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



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



  T.ToJson()/ string.FromJson< T>()// JSON序列化
T.ToJsv()/ string.FromJsv< T>( )//序列化JSV
T.ToXml()/ string.FromXml< T>()//序列化XML



手持转储utils的



递归打印的漂亮JSV转储格式

  T.PrintDump()

打印字符串到控制台解决的String.format() ARGS(如果有的话)

  string.Print(参数)



什么做你的序列化的DTO看起来像



您应该设法拿出的DTO的形状时做的第一步是填充,并将其打印到看看是什么样子。纵观XML输出块,我想出了这些DTO的:

  [DataContract(命名空间=HTTP:// SwitchKing。通用/实体/ RESTSimplified / 2010/07)] 
公共类RESTDataSource
{
[数据成员]
公共BOOL启用{搞定;组; }
[数据成员]
公共字符串描述{搞定;组; }
}

[CollectionDataContract(ITEMNAME =RESTDataSource,命名空间=HTTP://SwitchKing.Common/Entities/RESTSimplified/2010/07)]
公共类ArrayOfRESTDataSource:列表< RESTDataSource>
{
公共ArrayOfRESTDataSource(){}
公共ArrayOfRESTDataSource(IEnumerable的< RESTDataSource>收集):基地(集合){}
}

然后填充和转储他们:

  VAR DTO =新ArrayOfRESTDataSource {
新RESTDataSource {启用= true,则说明=MyTest的}};

dto.ToXml()打印()。



它打印到控制台:



<$ P ?$ p> < XML版本=1.0编码=UTF-8>< ArrayOfRESTDataSource的xmlns:I =http://www.w3.org/2001/XMLSchema-例如的xmlns =HTTP://SwitchKing.Common/Entities/RESTSimplified/2010/07>< RESTDataSource><简介> MyTest的< /说明><启用>真< /启用>< / RESTDataSource> < / ArrayOfRESTDataSource>



它看起来像我们所希望的。如果不调整上面的DTO,直到你得到一个数据块作为您预期的XML。



当你拥有的DTO的XML的形状相同,你就可以开始试图它们序列化:

  VAR DTO = xml.FromXml< ArrayOfRESTDataSource>(); 
dto.PrintDump();



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

  [
{
启用:没错,
说明:MyTest的
}
]

如果所有的字段都与预期值填充那么你就做,可以更新您的ServiceStack Web服务的DTO。


I've got the following chunk of XML data:

<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>

RESTDataSource can occur 0-n times.

And here's my classes:

[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; }
}

I read the above XML data from a server like this:

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 );
}

My question is: What do I need to change or decorate public RESTDataSource[] Data with to get the deseralization to work for the array? Serializing single RESTDataSource items work just fine, its just the array I can't get to work.

Thanks in advance.

Update 1

As @mythz suggested, I updated my code to this, but response.Data is still null. What did I not understand?

[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 ) { }
}

Update 2

The solution is in @mythz answer below, but just for completeness/clarity: What I did wrong was to add another level in my DTOs - the top-level class ArrayOfRESTDataSource is the one that actually has the sub items in XML so it is that one that should be of a collection type.

解决方案

You can use [CollectionDataContract(...)] to modify the serialization output for Arrays/Collections, see this previous answer for an example.

Debugging Serialization and Integration issues

The first step when trying to solve integration problems like this is to isolate the problem. i.e. remove everything else away and just focus on the problem. e.g. In this case I would just focus on the XML and the DTOs and decouple them from your services.

ServiceStack just uses .NET's Xml DataContractSerializer under the hood and doesn't add any extra transformations or byte overheads (it's just the raw DTOs serialized as-is), so if you can get it working outside of your services you can put the same DTOs back into your service and it will also work over the wire.

Handy ServiceStack Extension methods

ServiceStack provides convenient extension methods to serialize / de-serialize and analyze your data models:

Serialization / De-Serialization Extension methods

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

Handy Dump Utils

Recursively print a object-graph in Pretty JSV Dump Format

T.PrintDump()      

Print a string to the console resolving string.Format() args (if any)

string.Print(args)    

What do your Serialized DTOs look like

The first step you should be doing when trying to come up with the Shape of the DTOs is to populate and print them to see what it looks like. Looking at the chunk of XML output I came up with these DTOs:

[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) { }
}

Then populate and dump them:

var dto = new ArrayOfRESTDataSource { 
    new RESTDataSource { Enabled = true, Description = "MyTest" } };

dto.ToXml().Print();

Which prints to the Console:

<?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>

Which looks like what we want. If it doesn't tweak the above DTOs until you get the same chunk as your expected XML.

When you have the DTOs in the same shape of the XML you can start trying to serialize them:

var dto = xml.FromXml<ArrayOfRESTDataSource>();
dto.PrintDump();

Which will print this pretty object graph:

[
    {
        Enabled: True,
        Description: MyTest
    }
]

If all the fields are populated with the expected values then you are done and can update your ServiceStack web service DTOs.

这篇关于从XML数据反序列化阵列(在ServiceStack)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆