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

本文关键字:属性 获取 一个 我的 服务 REST WCF typeof JSON | 更新日期: 2023-09-27 18:36:56

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

这是我的方法:

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

这是我包含两个对象的基类:

[Serializable]
[DataContract]
[KnownType(typeof(Payment_Gateway))]
[KnownType(typeof(ReturnResponse))]
public class BaseType 
{
}

这是派生类之一:

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

这是另一个驱动类:

[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 $10. 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 $10 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 $9.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]"

}

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

DataContractJsonSerializer序列化多态类型时,它会添加一个__type字段来指示要序列化的类型。 从文档中:

如前所述,JSON 支持多态性,但有一些限制。JavaScript 是一种弱类型语言,类型标识通常不是问题。但是,使用 JSON 在强类型系统 (.NET) 和弱类型系统 (JavaScript) 之间进行通信时,保留类型标识非常有用。例如,数据协定名称为"Square"和"Circle"的类型派生自数据协定名称为"Shape"的类型。如果将"Circle"从 .NET 发送到 JavaScript,然后返回到需要"Shape"的 .NET 方法,则 .NET 端知道相关对象最初是"Circle"很有用 - 否则特定于派生类型的任何信息(例如,"Circle"上的"radius"数据成员)都可能会丢失。

为了保留类型标识,在将复杂类型序列化为 JSON 时,可以添加"类型提示",反序列化程序会识别提示并采取适当的操作。"类型提示"是一个 JSON 键/值对,键名称为"__type"(两个下划线后跟单词"type")。该值是格式为"DataContractName:DataContractNamespace"的 JSON 字符串(第一个冒号之前的任何内容都是名称)。使用前面的示例,可以按如下方式序列化"Circle"。

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

类型提示与 XML 架构实例标准定义的 xsi:type 属性非常相似,该属性在序列化/反序列化 XML 时使用。

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

更新

在 .Net 4.5 及更高版本中,可以通过将 DataContractJsonSerializerSettings.EmitTypeInformation 设置为 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);

或者,如果切换到 Json.NET,则其JsonSerializerSettings.TypeNameHandling设置允许您禁止输出其类型信息。