5

我有以下 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>

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<ArrayOfRESTDataSource>( xml );
}

我的问题是:我需要更改或装饰什么public RESTDataSource[] Data才能使反序列化对阵列起作用?序列化单个 RESTDataSource 项工作得很好,它只是我无法工作的数组。

提前致谢。

更新 1

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

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

更新 2

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

4

1 回答 1

8

您可以使用[CollectionDataContract(...)]修改 Arrays/Collections 的序列化输出,请参阅this previous answer for example

调试序列化和集成问题

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

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

方便的 ServiceStack 扩展方法

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

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

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

方便的转储工具

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

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

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

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

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

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

[
    {
        Enabled: True,
        Description: MyTest
    }
]

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

于 2012-11-18T20:50:15.603 回答