在C#中反序列化键值字符串

时间:2012-07-10 12:32:17

标签: c# .net query-string deserialization

我正在使用paypal NVP和NVP响应键值对字符串

示例

  

TOKEN = EC-3XXXXXXXXXXX154J&安培; BILLINGAGREEMENTACCEPTEDSTATUS = 1&安培; CHECKOUTSTATUS = PaymentActionNotInitiated&安培; TIMESTAMP = 2012-07-10T11:45:59Z&安培;的correlationID = ecf9bfe9b1168&安培; ACK =成功&安培; VERSION = 64.0&安培; BUILD = 3242673&安培; EMAIL = govind_1341920205_per @ gmail.com&安培; PAYERID = 3V85HKW32SXKG&安培; PAYERSTATUS =验证&安培; FIRSTNAME =戈文德&安培; LASTNAME =马尔维亚&安培; COUNTRYCODE = US&安培; SHIPTONAME =戈文德   Malviya& SHIPTOSTREET = 1 Main St& SHIPTOCITY = San   何塞&放大器; SHIPTOSTATE = CA&放大器; SHIPTOZIP = 95131&放大器; SHIPTOCOUNTRYCODE = US&放大器; SHIPTOCOUNTRYNAME =美国   States& ADDRESSSTATUS =已确认& CURRENCYCODE = USD& AMT = 30.90& SHIPPINGAMT = 0.00& HANDLINGAMT = 0.00& TAXAMT = 0.00& DESC = test EC   付款&安培; INSURANCEAMT = 0.00&安培; SHIPDISCAMT = 0.00&安培; PAYMENTREQUEST_0_CURRENCYCODE = USD&安培; PAYMENTREQUEST_0_AMT = 30.90&安培; PAYMENTREQUEST_0_SHIPPINGAMT = 0.00&安培; PAYMENTREQUEST_0_HANDLINGAMT = 0.00&安培; PAYMENTREQUEST_0_TAXAMT = 0.00&安培; PAYMENTREQUEST_0_DESC =测试   EC   付款&安培; PAYMENTREQUEST_0_INSURANCEAMT = 0.00&安培; PAYMENTREQUEST_0_SHIPDISCAMT = 0.00&安培; PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED =假安培; PAYMENTREQUEST_0_SHIPTONAME =戈文德   Malviya& PAYMENTREQUEST_0_SHIPTOSTREET = 1 Main   ST&安培; PAYMENTREQUEST_0_SHIPTOCITY =散   何塞&放大器; PAYMENTREQUEST_0_SHIPTOSTATE = CA&放大器; PAYMENTREQUEST_0_SHIPTOZIP = 95131&放大器; PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE = US&放大器; PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME =美国   国&安培; PAYMENTREQUESTINFO_0_ERRORCODE = 0

我想在强类型数据中对其进行去序列化,就像JavaScriptSerializer为json字符串做的那样。请不要使用字典提供解决方案我想避免魔术字符串,我可以在每个属性上添加属性。

我的班级是

 public class GetExpressCheckoutDetailsResponse : IPaypalResponse
    {
        public string Token { get; set; }
        public string BillingAgreementAcceptedStatus { get; set; }
        public string CheckoutStatus { get; set; }
        public string Timestamp { get; set; }
        public string CorrelationID { get; set; }
        public Status Acknowledgement { get; set; }
        public string Version { get; set; }
        public string Build { get; set; }
        public string Email { get; set; }
        public string PayerID { get; set; }
        public string PayerStatus { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string CountryCode { get; set; }
        public string ShiptoName { get; set; }
        public string ShiptoStreet { get; set; }
        public string ShipToCity { get; set; }
        public string ShipToState { get; set; }
        public string ShipToZip { get; set; }
        public string ShipToCountryCode { get; set; }
        public string ShipToCountryName { get; set; }
        public string AddressStatus { get; set; }
        public string CurrencyCode { get; set; }
        public string Amount { get; set; }
        public string ShippingAmount { get; set; }
        public string HandlingAmount { get; set; }
        public string TaxAmount { get; set; }
        public string Description { get; set; }
        public string InsuranceAmount { get; set; }
        public string ShipdiscAmount { get; set; }
        public string PaymentRequestCurrencycode { get; set; }
        public string PaymentRequestAmount { get; set; }
        public string PaymentRequestShippingAmount { get; set; }
        public string PaymentRequestHandlingAmount { get; set; }
        public string PaymentRequestTaxAmount { get; set; }
        public string PaymentRequestDescription { get; set; }
        public string PaymentRequestInsuranceAmount { get; set; }
        public string PaymentRequestShipdiscAmount { get; set; }
        public string PaymentRequestInsuranceOptionOffered { get; set; }
        public string PaymentRequestShipToName { get; set; }
        public string PaymentRequestShipToStreet { get; set; }
        public string PaymentRequestShipToCity { get; set; }
        public string PaymentRequestShipToState { get; set; }
        public string PaymentRequestShipToZip { get; set; }
        public string PaymentRequestShipToCountryCode { get; set; }
        public string PaymentRequestShipToCountryName { get; set; }
        public string PaymentRequestInfoErrorCode { get; set; }
    }

4 个答案:

答案 0 :(得分:3)

您可以使用LINQ将数据提取到Dictionary<TKey, TValue>,然后您可以使用它来映射您班级中的数据,例如

var paypalResponse = "...";
var data = paypalResponse.Split('&') 
                         .Select(x => x.Split('=')) 
                         .ToDictionary(x => x[0], x => x[1]);

然后你可以将它传递给GetExpressCheckoutDetailsResponse类的构造函数,甚至可以在其中执行此操作,例如。

public class GetExpressCheckoutDetailsResponse : IPaypalResponse
{
    public GetExpressCheckoutDetailsResponse(Dictionary<string, string> data)
    {
        this.Token = data["TOKEN"];
        this.BillingAgreementAcceptedStatus = data["BILLINGAGREEMENTACCEPTEDSTATUS"];
        ...
    }
}

对于这样的事情使用反射可能比它的价值更麻烦,因为您的属性不完全匹配,因此您需要为每个属性添加元数据属性。

答案 1 :(得分:2)

您可以使用HttpUtility.ParseQueryString将字符串转换为NameValueCollection。其余的只是reflection

string responseString = "TOKEN=EC......";
var dict = HttpUtility.ParseQueryString(responseString);
GetExpressCheckoutDetailsResponse respObj = new GetExpressCheckoutDetailsResponse();
foreach (var p in respObj.GetType().GetProperties())
{
    p.SetValue(respObj, dict[p.Name]);
}

//respObj is ready to use

答案 2 :(得分:1)

因此,由于您的问题没有现成的反序列化器,您应该执行以下操作:

  1. 为每个属性添加属性,代表paypal的响应'。
  2. 反映类实例的属性并将其缓存到Dictionary<string, PropertyInfo>,其中字符串是属性的值。
  3. 在paypal响应中迭代"some string".Split(..)方法的结果,收集字符串和值,然后将它们存储到您应该在字典中查找的相应属性中。

答案 3 :(得分:0)

在您的特定情况下,而不是重新发明轮子;你如何使用PayPal SDK?

http://paypal.github.io/sdk/

你想要的是Express Checkout SDK for C#

它已经拥有了您需要的所有字段以及正确的数据类型,它还具有在几个简单的函数调用后自动完成响应的所有调用/解析的附加好处。

手工构建自己的API调用并解析响应并不是最好的方法。当然,最终你将会让它发挥作用,但在你这样做之前,这将是一个耗时且容易出错的过程......