问题 有没有办法使DataContractSerializer输出更干净的XML?


使用DataContractSerializer序列化我的对象,我得到类似的输出

 <?xml version="1.0" encoding="utf-8" ?> 
 <AgentNotification xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/The.name.space.Notifications">
  <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
  <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" />        
 <_x003C_Email_x003E_k__BackingField>some@email.com</_x003C_Email_x003E_k__BackingField> 
  <_x003C_Name_x003E_k__BackingField>Random Person</_x003C_Name_x003E_k__BackingField> 
 <_x003C_Policies_x003E_k__BackingField>
 <PolicyNotification>
  <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
  <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
  <_x003C_ConfirmationNumber_x003E_k__BackingField>Some number</_x003C_ConfirmationNumber_x003E_k__BackingField>   
  </PolicyNotification>
 <PolicyNotification>
  </_x003C_Policies_x003E_k__BackingField>  
  </AgentNotification>

有没有办法输出正好的标签

<Id>
<Name>

等,不需要用属性覆盖我的类?

如果没有办法,每次正确的输出保证是相同的?因此,如果我使用它来渲染我的对象图是XML与文件生成的X *文档混搭,我将永远不会遇到我的节点更改名称并且文档空白正确的问题?


4170
now


起源

不。并且不要担心你的xml看起来如何。它只会导致心碎。 - Will
你应该回答Will。 - Chris Marisic


答案:


发生这种情况是因为您必须标记您的类型(例如 AgentNotification[Serializable]。什么时候 DataContractSerializer 遇到标有的类型 [Serializable] 但没有明确的 [DataContract],它会产生一个 默认合同 对于匹配方式的类型 BinaryFormatter 序列化一个类,即序列化 类的所有成员变量 - 甚至标记为私有的变量 - 按名字。对于 自动实现的属性,这意味着 秘密支持领域 按名称序列化;他们的名字是你所看到的奇特的元素名称。

解决这个问题的最简单方法是删除 [Serializable] 您的类的属性。除非你实际使用,否则你几乎肯定不需要它 BinaryFormatter 要么 SoapFormatter。这样做了, DataContractSerializer 现在将按名称序列化您的公共属性和字段,而不是按名称序列化公共和私有字段。


9
2017-07-19 07:28



这可能是我6年前想要的。但在某些时候我刚停止使用XSLT并开始使用Postal + RazorViewEngine来生成电子邮件内容。 - Chris Marisic


当您使用autoproperties时,.NET会创建长元素名称(例如,_x003C_Created_x003E_k__BackingField)。

如果您将它们更改为具有支持字段的属性,则它们将使用您的支持字段名称。您可以在不向代码添加任何属性的情况下执行此操作。

(除此之外,只需在类定义中添加[DataContract]属性即可大量整理XML - 尽管不完全。)


5
2018-02-23 03:52



我必须检查它有什么区别,我可以接受在类级别放置一个属性,特别是因为这些类是数据交换,即使它们没有通过WCF公开 - Chris Marisic
我对你的经历很感兴趣。序列化似乎定义不明确,并且存在多种解决方案。 - David White


DataContractSerializer 将序列化所有公共属性(如果您没有指定任何内容 - 从.NET 3.5 SP1开始可能),或者(我更喜欢的方法)您使用[DataMember]属性标记的任何内容。

所以你能做的最好的就是用一个标记你的课程 [DataContract] 属性,以及您在数据合同中真正想要的所有成员(属性,字段等) [DataMember] 属性。

DataContractSerializer实际上不允许更多的控制 - 你可以非常清楚地定义(使用这种明确的“选择加入”方法) 什么 获得序列化,但你几乎没有控制权 怎么样 它被序列化了。

但你真的需要吗?真?

如果是这样,你可能不得不将XmlSerializer用于该序列化过程 - 在那里你可以获得更多的控制权 怎么样 事物是序列化的(但作为一个缺点,XmlSerializer将序列化每个未明确标记为a的公共属性 [XmlIgnore] 属性 - “选择退出”方案)。

看看Dan Rigsby的 博客文章 关于DataContractSerializer和XmlSerializer之间的差异以及它们各自提供的内容。


1
2017-12-23 17:04



我确实希望它序列化所有属性,XMLSerializer甚至不是一个选项,因为我的对象中有一个IList。我问的是命名方案,因为如果属性与我的类对象完全匹配,在我的转换文档中会更容易。 - Chris Marisic
你用[DataMember]属性装饰了你的类和属性吗?您可以使用以下命令定义名称:[DataMember(Name =“xyz”)] - 这对您的情况有帮助吗?