[英]Serializing a class to JSON generated by xsd.exe using WCF
I want to write a RESTful Webservice with WCF which is able to reply in JSON and XML. 我想用WCF编写RESTful Webservice,它能够以JSON和XML进行回复。 I have a XML schema from which I generated my classes by using xsd.exe
. 我有一个XML模式,我通过使用xsd.exe
生成我的类。 Everthing works fine as long as I request XML, but it fails if I want JSON as response. 只要我请求XML,Everthing就可以正常工作,但如果我想要JSON作为响应,它就会失败。
The System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter
throws a System.Collections.Generic.KeyNotFoundException
. System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter
抛出System.Collections.Generic.KeyNotFoundException
。 The problem is, what I found out so far, that xsd.exe
does not generate DataContract
and DataMember
Attributes. 问题是,到目前为止我发现, xsd.exe
不生成DataContract
和DataMember
属性。 Is there any solution to this where I do not need to use the SvcUtil.exe
, because therefore I would need to change my schema.. 是否有任何解决方案,我不需要使用SvcUtil.exe
,因为我需要更改我的架构..
That is the code where it fails, JsonDispatchMessageFormatter
is of the type MultiplexingDispatchMessageFormatter
. 这是失败的代码, JsonDispatchMessageFormatter
的类型为MultiplexingDispatchMessageFormatter
。 (Which is the default type anyway) (无论如何,这是默认类型)
var headers = requestProperty.Headers[HttpRequestHeader.Accept] ?? requestProperty.Headers[HttpRequestHeader.ContentType];
if (headers != null && headers.Contains("application/json"))
{
return this.JsonDispatchMessageFormatter.SerializeReply(messageVersion, parameters, result);
}
Generated code: 生成的代码:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="...")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="...", IsNullable=false)]
public partial class Incident {
private long incidentIdField;
/// <remarks/>
public long IncidentId {
get {
return this.incidentIdField;
}
set {
this.incidentIdField = value;
}
}
}
The reason you are seeing private fields rather than public properties in your JSON is that xsd.exe
has marked your classes with [SerializableAttribute]
. 您在JSON中看到私有字段而不是公共属性的原因是xsd.exe
已使用[SerializableAttribute]
标记了您的类。 When this attribute is applied to a type, it signifies that instances of the type can be serialized by serializing all private and public fields -- not the properties. 将此属性应用于某个类型时,它表示可以通过序列化所有私有字段和公共字段 (而不是属性)来序列化该类型的实例。
Under the covers, WCF uses DataContractJsonSerializer
to serialize to and from JSON. 在封面下,WCF使用DataContractJsonSerializer
与JSON进行序列化。 When this serializer goes to generate a default, implicit data contract for a type without data contract attributes , it notices the [Serializable]
attribute and respects it, generating a contract to serialize and deserialize public and private fields. 当此序列化程序为没有数据协定属性的类型生成默认的隐式数据协定时,它会注意到[Serializable]
属性并尊重它,生成一个序列化和反序列化公共和私有字段的合同。 This is what you are seeing. 这就是你所看到的。
What is a bit odd is that xsd.exe
doesn't need to add [Serializable]
to its generated classes. 有点奇怪的是, xsd.exe
不需要将[Serializable]
添加到其生成的类中。 XmlSerializer
completely ignores this attribute since it can only serialize public members . XmlSerializer
完全忽略此属性,因为它只能序列化公共成员 。 (It also completely ignores data contract attributes. Similarly the data contract serializers all ignore XmlSerializer
control attributes .) (它也完全忽略了数据契约属性。类似地,数据契约序列化器都忽略了XmlSerializer
控件属性 。)
Unfortunately, I don't see any xsd
command line switches to disable this attribute. 不幸的是,我没有看到任何xsd
命令行开关来禁用此属性。 Thus you're going to do some sort of manual fix: 因此,您将要进行某种手动修复:
Remove [System.SerializableAttribute()]
from the generated classes. 从生成的类中删除[System.SerializableAttribute()]
。 This should be harmless unless you're using BinaryFormatter
somewhere; 除非你在某处使用BinaryFormatter
否则这应该是无害的; you probably are not. 你可能不是。
Add [DataContract]
and [DataMember]
attributes to the generated classes. 将[DataContract]
和[DataMember]
属性添加到生成的类中。 (Remember, these are ignored by XmlSerializer
so you're pre-existing XML schema will be unchanged.) (请记住, XmlSerializer
会忽略它们 ,因此您预先存在的XML架构将保持不变。)
You might also consider generating contract-appropriate classes with SvcUtil.exe
then using automapper to map your old classes to your new classes. 您还可以考虑使用SvcUtil.exe
生成与合约相关的类,然后使用automapper将旧类映射到新类。
Or you might consider switching to a different JSON serializer, such as json.net , where you can control whether to ignore or respect [Serializable]
. 或者您可以考虑切换到不同的JSON序列化程序,例如json.net ,您可以在其中控制是忽略还是尊重[Serializable]
。 The questions How to set Json.Net as the default serializer for WCF REST service and C# WCF REST - How do you use JSON.Net serializer instead of the default DataContractSerializer? 问题如何将Json.Net设置为WCF REST服务和C#WCF REST 的默认序列化程序 - 如何使用JSON.Net序列化程序而不是默认的DataContractSerializer? should get you started. 应该让你开始。
As an aside, WCF rest may not be the best technology for you if you want precise control over your XML and JSON formatting. 另外,如果您想要精确控制XML和JSON格式,WCF休息可能不是最适合您的技术。 ASP.NET Web API allows for much more precise control of serialization formats by using json.net ; ASP.NET Web API允许使用json.net更精确地控制序列化格式; see JSON and XML Serialization in ASP.NET Web API along with Setting IgnoreSerializableAttribute Globally in Json.net and .NET WebAPI Serialization k_BackingField Nastiness . 请参阅ASP.NET Web API中的JSON和XML序列化以及在Json.net和.NET WebAPI序列化k_BackingField Nastiness中 全局设置IgnoreSerializableAttribute 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.