【问题标题】:Serializing a class to JSON generated by xsd.exe using WCF使用 WCF 将类序列化为 xsd.exe 生成的 JSON
【发布时间】:2026-01-20 06:05:02
【问题描述】:

我想用 WCF 编写一个 RESTful Web 服务,它能够以 JSON 和 XML 回复。我有一个 XML 模式,我使用xsd.exe 从中生成了我的类。只要我请求 XML,一切都可以正常工作,但如果我想要 JSON 作为响应,它就会失败。

System.ServiceModel.Dispatcher.MultiplexingDispatchMessageFormatter 抛出 System.Collections.Generic.KeyNotFoundException。问题是,到目前为止,我发现xsd.exe 不会生成DataContractDataMember 属性。有没有什么解决方案我不需要使用SvcUtil.exe,因为因此我需要更改我的架构..

那是它失败的代码,JsonDispatchMessageFormatter 的类型是MultiplexingDispatchMessageFormatter。 (反正这是默认类型)

var headers = requestProperty.Headers[HttpRequestHeader.Accept] ?? requestProperty.Headers[HttpRequestHeader.ContentType];
if (headers != null && headers.Contains("application/json"))
{
    return this.JsonDispatchMessageFormatter.SerializeReply(messageVersion, parameters, result);
}

生成的代码:

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

【问题讨论】:

  • 在重新调整之前尝试添加WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";
  • "application/json" 添加到传出响应中允许我现在序列化为json,但我还有一个问题。 XML 和 JSON 都序列化支持字段而不是属性。我可以为我的服务合同使用属性XmlSerializerFormat 来避免XML 的这种情况,但是我再次不能使用JSON,因为它不喜欢这个属性。它建议我使用DataContractFormatAttribute,这将再次导致序列化支持字段..

标签: c# json xml wcf serialization


【解决方案1】:

您在 JSON 中看到私有字段而不是公共属性的原因是 xsd.exe 已将您的类标记为 [SerializableAttribute]。当此属性应用于一个类型时,它表示该类型的实例可以通过序列化所有私有和公共字段来序列化——而不是属性。

在幕后,WCF 使用DataContractJsonSerializer 与 JSON 进行序列化。当此序列化程序为没有data contract attributes 的类型生成默认的隐式数据协定时,它会注意到[Serializable] 属性并尊重它,生成一个对公共和私有字段进行序列化和反序列化的协定。这就是你所看到的。

有点奇怪的是xsd.exe 不需要将[Serializable] 添加到其生成的类中。 XmlSerializer 完全忽略此属性,因为它只能序列化公共成员。 (它也完全忽略了数据契约属性。同样,数据契约序列化器都忽略了XmlSerializer control attributes。)

不幸的是,我没有看到任何xsd command line switches 来禁用此属性。因此,您将进行某种手动修复:

顺便说一句,如果您想精确控制 XML 和 JSON 格式,WCF rest 可能不是最适合您的技术。 ASP.NET Web API 允许使用 更精确地控制序列化格式;请参阅 JSON and XML Serialization in ASP.NET Web API 以及 Setting IgnoreSerializableAttribute Globally in Json.net.NET WebAPI Serialization k_BackingField Nastiness

【讨论】: