【问题标题】:Deserialize key value string in C#在 C# 中反序列化键值字符串
【发布时间】:2012-07-10 12:32:17
【问题描述】:

我正在使用 paypal NVP 并且 NVP 在键值对字符串中响应

例子

TOKEN = EC-3XXXXXXXXXXX154J&BILLINGAGREEMENTACCEPTEDSTATUS = 1&CHECKOUTSTATUS = PaymentActionNotInitiated&TIMESTAMP = 2012-07-10T11:45:59Z&CORRELATIONID=ecf9bfe9b1168&ACK=Success&VERSION=64.0&BUILD=3242673&EMAIL=govind_1341920205_per@gmail.com&PAYERID=3V85HKW32SXKG&PAYERSTATUS=verified&FIRSTNAME=Govind&LASTNAME=Malviya&COUNTRYCODE=US&SHIPTONAME=Govind Malviya&SHIPTOSREET=1 Main St&SHIPTOCITY=San Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United States&ADDRESSSTATUS=已确认&CURRENCYCODE=USD&AMT=30.90&SHIPPINGAMT=0.00&HANDLINGAMT=0.00&TAXAMT=0.00&DESC=测试EC payment&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_ 欧共体 payment&PAYMENTREQUEST_0_INSURANCEAMT=0.00&PAYMENTREQUEST_0_SHIPDISCAMT=0.00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Govind Malviya&PAYMENTREQUEST_0_SHIPTOSTREET=1 主要 St&PAYMENTREQUEST_0_SHIPTOCITY=San Jose&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; }
    }

【问题讨论】:

  • 你对使用反射有什么看法?我怀疑是否有一个现成的序列化程序可以做你想做的事。
  • 反射和属性听起来不错
  • @Codesleuth 我想可能会有很多不同的响应,但反映 single 固定类对我来说似乎也太过分了。
  • 我解决了我的问题检查我的答案。
  • 如果我是你,我会删除你在问题中输入的一些代码,它看起来像敏感数据!

标签: c# .net query-string deserialization


【解决方案1】:

您可以使用 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"];
        ...
    }
}

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

【讨论】:

  • @GovindKamalaPrakashMalviya 查看您的答案,您使用了提供给您的解决方案,但换掉了映射部分。所以我们解决了你的问题。您应该始终标记为您提供最大帮助的答案(即使它不是完整的解决方案)。
  • 我还没有接受任何答案,你怎么知道这个?感谢您的反对。
  • @GovindKamalaPrakashMalviya 如果你发布你的解决方案很好,但你不应该把它作为一个新的答案发布,给人的印象是你会接受那个 - 它违背了整个观点网站。
  • 所以你的意思是不要发布答案并接受一半的答案对吗?太棒了!
  • @GovindKamalaPrakashMalviya 您基本上采用了我给您的解决方案并对其进行了修改以满足您的需求(这就是 SO 的全部意义所在)。但是,您应该更新您的答案以说“这是我最终得到的解决方案”并接受给您最大帮助的答案(无论它是否只是整体解决方案的一部分)。否则,首先发布答案的人有什么意义?这不是很好的礼仪......
【解决方案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

【讨论】:

  • 对此我要说的唯一一件事是您添加了对System.Web 的依赖只是为了一个小的解析功能,对我来说似乎有点OTT(除非OP 已经使用System.Web)。
【解决方案3】:

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

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

【讨论】:

  • @GovindKamalaPrakashMalviya 不要忘记接受答案。
【解决方案4】:

在您的特定情况下,不要重新发明轮子;使用 PayPal SDK 怎么样?

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

你想要的是Express Checkout SDK for C#

它已经拥有您需要的所有字段以及正确的数据类型,并且它还有一个额外的好处,即在几个简单的函数调用之后自动执行所有响应的调用/解析。

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

【讨论】:

  • 两个链接都坏了。你能更新一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
相关资源
最近更新 更多