有没有办法让 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>[email protected]</_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* 文档混合以生成文件,我将永远不会遇到我的节点更改名称并且文档显示为空白的问题,正确吗?
Using the DataContractSerializer to serialize my object I get an output similar to
<?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>[email protected]</_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>
Is there any way for it to output tags that are just
<Id>
<Name>
etc, without the need to cover my classes with attributes?
If there's not a way the output of this is guaranteed to be the same every time correct? So that if I use this to render my object graphs are XML to mash up with an X* document for file generation that I'll never run into an issue where my nodes change names and the document comes out blank correct?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
发生这种情况是因为您必须使用
[可序列化]
。当DataContractSerializer
遇到标有[Serialized]
但没有显式[DataContract]
,它会生成一个 默认合约,用于匹配BinaryFormatter
序列化一个类,即序列化所有类的成员变量——甚至是按名称标记为私有的变量。对于自动实现的属性,这意味着秘密支持字段按名称序列化;它们的名字就是你所看到的特殊元素名称。解决此问题的最简单方法是从类中删除
[Serializable]
属性。您几乎肯定不需要它,除非您实际上使用BinaryFormatter
或SoapFormatter
。完成此操作后,DataContractSerializer
现在将按名称序列化您的公共属性和字段,而不是按名称序列化公共和私有字段。This is happening because you must have marked your types (e.g.
AgentNotification
) with[Serializable]
. WhenDataContractSerializer
encounters a type marked with[Serializable]
but no explicit[DataContract]
, it generates a default contract for the type that matches howBinaryFormatter
serializes a class, which is to serialize all member variables of a class — even variables marked as private — by name. For auto-implemented properties, this means the secret backing fields get serialized by name; their names are the peculiar element names you are seeing.The easiest way to solve this is to remove the
[Serializable]
attribute from your classes. You almost certainly don't need it unless you are actually usingBinaryFormatter
orSoapFormatter
. Having done so,DataContractSerializer
will now serialize your public properties and fields by name, rather than public and private fields by name.当您使用自动属性时,.NET 将创建长元素名称(例如 _x003C_Created_x003E_k__BackingField)。
如果您将它们更改为带有支持字段的属性,它们将改为使用您的支持字段名称。您无需在代码中添加任何属性即可做到这一点。
(除此之外,只需在类定义中添加 [DataContract] 属性即可使 XML 变得更加整洁——尽管并不完全。)
The long element names (such as, _x003C_Created_x003E_k__BackingField) are created by .NET when you use autoproperties.
If you changed them to properties with backing fields, they would instead use your backing field names. You can do that without adding any attributes to your code.
(Beyond that, simply adding a [DataContract] attribute to your class definition will tidy up your XML a lot -- though not completely.)
DataContractSerializer 将序列化所有公共属性(如果您未指定任何内容 - 从 .NET 3.5 SP1 开始可能),或(我更喜欢的方法)使用 [DataMember] 属性标记的任何内容。
因此,您能做的最好的事情就是使用
[DataContract]
属性标记您的类,并使用[ 在数据协定中标记您真正想要的所有成员(属性、字段等)。 DataMember]
属性。DataContractSerializer 并没有真正允许比这更多的控制 - 您可以非常清楚地定义(使用这种显式的“选择加入”方法)什么被序列化,但是您对几乎没有控制权>如何它被序列化。
但你真的需要那个吗?真的吗?
如果是这样,您可能必须使用 XmlSerializer 来执行该序列化过程 - 在那里您可以更好地控制如何序列化事物(但缺点是,XmlSerializer 将序列化每个公共属性未使用
[XmlIgnore]
属性显式标记 - “选择退出”方案)。查看 Dan Rigsby 的 博客文章。
The
DataContractSerializer
will serialize either all public properties (if you don't specify anything - possible as of .NET 3.5 SP1), or (the approach I prefer) anything you label with a [DataMember] attribute.So the best you can do is mark your class with a
[DataContract]
attribute, and all the members (properties, fields, etc.) that you really want in your data contract with a[DataMember]
attribute.The DataContractSerializer doesn't really allow much more control than that - you can define quite clearly (using this explicit "opt-in" approach) what gets serialized, but you have little or no control over how it gets serialized.
But do you really need that? REALLY?
If so, you'll probably have to use the XmlSerializer for that serialization process instead - there you can get more control over how things are serialized (but as a drawback, the XmlSerializer will serialize every public property that's not explicitly marked with a
[XmlIgnore]
attribute - an "opt-out" scheme).Check out Dan Rigsby's blog post on the differences between DataContractSerializer and XmlSerializer and what each of them has to offer.
最后我遇到了同样的麻烦,所以你只需要将 [DataContract] 和 [DataMember] 添加到模型中即可。
I met the same trouble, at last, so you just need to add [DataContract]和[DataMember] to the model.