在 WCF REST 服务中使用 typeof 时,在我的 JSON 中获得一个额外的 属性

Get an extra property in my JSON when using typeof in a WCF REST service

我有一个 Restful WCF 方法,它根据方法内部的条件返回 2 个对象(2 个不同的 class)。

这是我的方法:

public Model.BaseType returnPayment_Gateway()
{
    IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
    WebHeaderCollection headers = request.Headers;

    Model.Payment_Gateway payment_Gateway=null;
    if (headers["ServiceAuthentication"] != null)
    {
     string   ServiceAuthentication = headers["ServiceAuthentication"].ToString();
      bool  serviceAuth = Service_Authentication(ServiceAuthentication);

      DAL.DataManager dal = new DAL.DataManager();

        if (serviceAuth == true)
        {
            payment_Gateway = dal.Get_Payment_Gateway();
        }
    }
    else
    {
            // Create a new response to return
          return new Model.ReturnResponse() { StatusCode = 201, StatusDescription = "Authentication Fails" };
    }

     return payment_Gateway;
}

这是我的基础 class,包含两个对象:

[Serializable]
[DataContract]
[KnownType(typeof(Payment_Gateway))]
[KnownType(typeof(ReturnResponse))]

public class BaseType 
{

}

这是派生的 classes:

[DataContract]
public class Payment_Gateway:BaseType
{
    [DataMember]
    public string Gateway { get; set; }

这是另一个驱动 class:

[DataContract]
public class ReturnResponse:BaseType
{
    [DataMember]
    public int StatusCode { get; set; }

    [DataMember]
    public string StatusDescription { get; set; }

这是在我的 .SVC 中我如何调用此方法:

public   Model.BaseType Payment_Gateway()
{
   return GetCustomerInfo.Instance.returnPayment_Gateway();
}

这是我的服务界面:

[WebInvoke(Method = "GET",
                            ResponseFormat = WebMessageFormat.Json,
                            BodyStyle = WebMessageBodyStyle.Bare,
                           UriTemplate = "Payment_Gateway")]
Model.BaseType Payment_Gateway();

我的问题:

我收到的 Json 响应有 1 行,我不确定它来自哪里以及如何删除它。 这一行:

 "__type": "Payment_Gateway:#CustomerPortal.Model",

这是我在 Soap 中得到的完整响应 UI。

 {
  "__type": "Payment_Gateway:#CustomerPortal.Model",
"Gateway": "[\r\n        {\"Payment_Gateway_ID\":\"40\",\"Payment_Gateway_Name\":\"Speedpay\",\"Payment_Gateway_URL\":\"https:\/\/paynow7.speedpay.com\/CarFinance\/index.asp\",\"Payment_Gateway_Description\":\"Speedpay is a Third-party bill payment vendor that provides CarFinance.com's customers the convenience and flexibility of making electronic payments, along with the security and peace-of-mind that comes from retaining total control over your bills. Western Union Speedpay charges a convenience fee of . CarFinance.com does not receive any portion of the convenience fee. The fee, which is in addition to your car payment, is paid directly to Western Union Speedpay for providing this service to our customers.\"},\r\n    {\"Payment_Gateway_ID\":\"41\",\"Payment_Gateway_Name\":\"Western Union - Quick Collect\",\"Payment_Gateway_URL\":\"https:\/\/www.westernunion.com\/us\/en\/home.html\",\"Payment_Gateway_Description\":\"Western Union Quick Collect service is a fast and convenient way to deliver funds -- especially on a due date! Within minutes of your completed payment transaction, Quick Collect delivers an electronic fund transfer notification to CarFinance.com. Western Union charges a  service fee that typically is less expensive than the cost of overnight delivery. Please note: This Western Union service will accept cash only.\"},\r\n    {\"Payment_Gateway_ID\":\"42\",\"Payment_Gateway_Name\":\"MoneyGram\",\"Payment_Gateway_URL\":\"http:\/\/moneygram.com\/us\/en\",\"Payment_Gateway_Description\":\"MoneyGram Bill Payments Services is set up to allow consumers make payments to CarFinance.com. MoneyGram charges a fee of .99 for this service. CarFinance.com does not receive any portion of the convenience fee. The fee, which is in addition to your car payment, is paid directly to MoneyGram for providing this service to our customers. Bill Payment Services also enable consumers to load and reload prepaid debit cards. To find an agent near you or pay online, go to \"},\r\n    {\"Payment_Gateway_ID\":\"43\",\"Payment_Gateway_Name\":\"Mail your payment\",\"Payment_Gateway_URL\":\"\",\"Payment_Gateway_Description\":\"Payments are processed and posted to accounts Monday through Friday (excluding holidays). Please allow 10 days for mailing if you're mailing your payment.\r\n\r\nCarFinance\r\nPO Box 660057\r\nDallas, TX 75266-0057\"}\r\n]"

}

DataContractJsonSerializer serializes a polymorphic type, it adds a __type field to indicate the type being serialized. From the docs:

As stated earlier, polymorphism is supported in JSON with some limitations. JavaScript is a weakly-typed language and type identity is normally not an issue. However, when using JSON to communicate between a strongly-typed system (.NET) and a weakly-typed system (JavaScript), it is useful to preserve type identity. For example, types with data contract names "Square" and "Circle" derive from a type with a data contract name of "Shape". If "Circle" is sent from .NET to JavaScript and is later returned to a .NET method that expects "Shape", it is useful for the .NET side to know that the object in question was originally a "Circle" - otherwise any information specific to the derived type (for example, "radius" data member on "Circle") may be lost.

To preserve type identity, when serializing complex types to JSON a "type hint" can be added, and the deserializer recognizes the hint and acts appropriately. The "type hint" is a JSON key/value pair with the key name of "__type" (two underscores followed by the word "type"). The value is a JSON string of the form "DataContractName:DataContractNamespace" (anything up to the first colon is the name). Using the earlier example, "Circle" can be serialized as follows.

{"__type":"Circle:http://example.com/myNamespace","x":50,"y":70,"radius":10}

The type hint is very similar to the xsi:type attribute defined by the XML Schema Instance standard and used when serializing/deserializing XML.

在您的情况下,您的 BaseType 可以是 Payment_GatewayReturnResponse,因此添加了此信息。

更新

在 .Net 4.5 及更高版本中,可以通过设置 DataContractJsonSerializerSettings.EmitTypeInformation to EmitTypeInformation.Never:

来抑制带有 DataContractJsonSerializer 的类型信息的输出
var settings = new DataContractJsonSerializerSettings { EmitTypeInformation = EmitTypeInformation.Never };
var serializer = new DataContractJsonSerializer(typeof(BaseType), settings); // No type hints will be emitted.

拥有序列化程序后,您可以使用以下辅助方法生成 JSON 字符串:

public static class DataContractJsonSerializerHelper
{
    private static MemoryStream GenerateStreamFromString(string value)
    {
        return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
    }

    public static string GetJson<T>(T obj, DataContractJsonSerializer serializer)
    {
        using (var memory = new MemoryStream())
        {
            serializer.WriteObject(memory, obj);
            memory.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(memory))
            {
                return reader.ReadToEnd();
            }
        }
    }

    public static string GetJson<T>(T obj) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetJson(obj, serializer);
    }
}

然后像这样称呼它

var json = DataContractJsonSerializerHelper.GetJson(obj, serializer);

或者,如果您 switch to Json.NET, its JsonSerializerSettings.TypeNameHandling setting allows you to suppress output of its type information