【问题标题】:How to map out array of dictionaries?如何映射出字典数组?
【发布时间】: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 中获得了来自paymentDictpaymentDict,然后是该卡中的所有信息,而在另一个示例中,您尝试从数据本身获取所有信息
  • @Schottky 如何使用第二种方法获取卡片字典?
  • 我的意思是将data["card"] 放在map 方法中,比如if let data = response["data"] as? [[String:Any]]; data.map { billingDetails -&gt; if let card = billingDetails["card"] ... }
  • @Schottky 是的,效果很好。如果您想将其放入答案中,我会将其设置为已接受的答案。谢谢!!!

标签: ios swift


【解决方案1】:

重申 cmets: 这里的问题是,在self.paymentMethods = data.map({ (card) -&gt; PaymentMethod in ... 行中,卡片不是卡片([String:Any]),而是包含大量信息的整个数据对象。因此,要解决此问题,您只需从 data 对象中获取 card,如下所示:

self.paymentMethods = data.map { billingDetails in
    let card = billingDetails["card"] ?? [:]
    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)

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-17
    • 2017-04-06
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 2023-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多