【发布时间】:2021-05-27 01:20:06
【问题描述】:
我正在尝试将从服务器接收到的付款方式对象映射到字典数组中。到目前为止,我已经能够获得单独的字典,但我无法将它们放入数组中。
这是我想用来映射数据的结构:
struct PaymentMethod: Identifiable, Codable {
var id: String? = UUID().uuidString
var brand: String
var expMonth: Int
var expYear: Int
var last4: String
init?(paymentDict: [String: Any]) {
guard let card = paymentDict["card"] as? [String: Any] else {
print("There is no \"card\" key or it's not a [String: Any] in: \(paymentDict)")
return nil
}
guard let brand = card["brand"] as? String else {
print("There is no \"brand\" key or it's not a String in: \(card)")
return nil
}
guard let expMonth = card["exp_month"] as? Int else {
print("There is no \"expMonth\" key or it's not a Int in: \(card)")
return nil
}
guard let expYear = card["exp_year"] as? Int else {
print("There is no \"expYear\" key or it's not a Int in: \(card)")
return nil
}
guard let last4 = card["last4"] as? String else {
print("There is no \"last4\" key or it's not a Int in: \(card)")
return nil
}
self.brand = brand
self.expMonth = expMonth
self.expYear = expYear
self.last4 = last4
}
}
使用上述结构,我可以打印出每个单独的支付方式对象,但我无法将它们存储到支付方式数组中。我使用以下函数来做到这一点:
func listPaymentMethods(customerID: String) {
FirebaseReferenceManager.functions.httpsCallable("listPaymentMethods").call(["customer_id": customerID]) { (response, error) in
if let error = error {
print("failed to list customer's payment methods: \(error.localizedDescription)")
}
if let response = response?.data as? [String: Any] {
if let data = response["data"] as? [[String:Any]] {
data.forEach { method in
if let payment = PaymentMethod(paymentDict: method) {
print("payment found \(payment)")
} else {
print("invalid payment")
}
}
} else {
print("No data in \(response)")
}
}
}
}
这会打印出以下内容:
payment found PaymentMethod(id: Optional("495722B5-F311-4D15-BECC-A952F10FEDD3"), brand: "mastercard", expMonth: 4, expYear: 2025, last4: "4444")
和
payment found PaymentMethod(id: Optional("0C59C57F-5992-479B-8057-E6EF26E68389"), brand: "visa", expMonth: 12, expYear: 2045, last4: "4242")
我尝试修改我的函数以将付款方式存储到付款方式数组@Published var paymentMethods = [PaymentMethod](),但是当我打印结果时,所有数据都返回为nil。
func listPaymentMethods(customerID: String) {
FirebaseReferenceManager.functions.httpsCallable("listPaymentMethods").call(["customer_id": customerID]) { (response, error) in
if let error = error {
print("failed to list customer's payment methods: \(error.localizedDescription)")
}
if let response = response?.data as? [String: Any] {
if let data = response["data"] as? [[String:Any]] {
self.paymentMethods = data.map({ (card) -> PaymentMethod in
let brand = card["brand"] as? String ?? ""
let expMonth = card["exp_month"] as? Int ?? 0
let expYear = card["exp_year"] as? Int ?? 0
let last4 = card["last4"] as? String ?? ""
return PaymentMethod(brand: brand, expMonth: expMonth, expYear: expYear, last4: last4)
})
print(self.paymentMethods)
} else {
print("No data in \(response)")
}
}
}
}
打印data = response["data"] as? [[String:Any]] 返回以下内容(这是我要绘制的数据):
[["object": payment_method, "billing_details": {
address = {
city = "<null>";
country = US;
line1 = "<null>";
line2 = "<null>";
"postal_code" = 45678;
state = "<null>";
};
email = "<null>";
name = "<null>";
phone = "<null>";
}, "metadata": {
}, "created": 1622026254, "type": card, "livemode": 0, "customer": cus_JWaE2JEtbcI0JM, "card": {
brand = mastercard;
checks = {
"address_line1_check" = "<null>";
"address_postal_code_check" = pass;
"cvc_check" = pass;
};
country = US;
"exp_month" = 4;
"exp_year" = 2025;
fingerprint = jI4Pm7ac3fZjdYDN;
funding = credit;
"generated_from" = "<null>";
last4 = 4444;
networks = {
available = (
mastercard
);
preferred = "<null>";
};
"three_d_secure_usage" = {
supported = 1;
};
wallet = "<null>";
}, "id": pm_1IvKK9LVD5W50FFKvSbe2eA0], ["customer": cus_JWaE2JEtbcI0JM, "livemode": 0, "type": card, "id": pm_1IuyMzLVD5W50FFK2heBUTai, "billing_details": {
address = {
city = "<null>";
country = US;
line1 = "<null>";
line2 = "<null>";
"postal_code" = 123456;
state = "<null>";
};
email = "<null>";
name = "<null>";
phone = "<null>";
}, "metadata": {
}, "created": 1621941861, "card": {
brand = visa;
checks = {
"address_line1_check" = "<null>";
"address_postal_code_check" = pass;
"cvc_check" = pass;
};
country = US;
"exp_month" = 12;
"exp_year" = 2045;
fingerprint = KKSbyUhUcKKSyto0;
funding = credit;
"generated_from" = "<null>";
last4 = 4242;
networks = {
available = (
visa
);
preferred = "<null>";
};
"three_d_secure_usage" = {
supported = 1;
};
wallet = "<null>";
}, "object": payment_method]]
我想要绘制的唯一数据是品牌、到期月份和年份,以及信用卡号的最后 4 位。
最新版本
if let response = response?.data as? [String: Any] {
if let data = response["data"] as? [String: Any] {
if let card = data["card"] as? [[String:Any]] {
self.paymentMethods = card.map({ (card) -> PaymentMethod in
let brand = card["brand"] as? String ?? ""
let expMonth = card["exp_month"] as? Int ?? 0
let expYear = card["exp_year"] as? Int ?? 0
let last4 = card["last4"] as? String ?? ""
return PaymentMethod(brand: brand, expMonth: expMonth, expYear: expYear, last4: last4)
})
}
}
print(self.paymentMethods)
}
任何帮助将不胜感激,谢谢! :)
【问题讨论】:
-
为什么不直接使用
self.paymentMethods = data.map { PaymentMethod($0) }? -
另外,原因是在您的
PaymentMethod-struct 中,您从card-Dictionary 中获得了来自paymentDict的paymentDict,然后是该卡中的所有信息,而在另一个示例中,您尝试从数据本身获取所有信息 -
@Schottky 如何使用第二种方法获取卡片字典?
-
我的意思是将
data["card"]放在map 方法中,比如if let data = response["data"] as? [[String:Any]]; data.map { billingDetails -> if let card = billingDetails["card"] ... } -
@Schottky 是的,效果很好。如果您想将其放入答案中,我会将其设置为已接受的答案。谢谢!!!