简体   繁体   English

为什么我的 json 响应对象返回 nil?

[英]Why are my json response objects returning nil?

I have some json:我有一些 json:

   {
   "wallets":[
      {
         "fundingProviderName":"tns_cof",
         "authLimit":75,
         "pinRequired":true,
         "wallets":[
            {
               "authLimit":75,
               "isCardSupported":true,
               "paymentProcessorId":6,
               "mainDisplayText":"...0013",
               "imageUrl":"https://az755244.vo.msecnd.net/paymentimages/visa2.png",
               "userPaymentSourceId":9756,
               "secondaryDisplayText":"12/30",
               "expDate":"2030-12-31T23:59:59Z",
               "cardIssuer":"Visa"
            },
            {
               "authLimit":75,
               "isCardSupported":true,
               "paymentProcessorId":7,
               "mainDisplayText":"...1020",
               "imageUrl":"https://az755244.vo.msecnd.net/paymentimages/mastercard2.png",
               "userPaymentSourceId":9757,
               "secondaryDisplayText":"12/25",
               "expDate":"2025-12-31T23:59:59Z",
               "cardIssuer":"Mastercard"
            },
            {
               "authLimit":75,
               "isCardSupported":true,
               "paymentProcessorId":8,
               "mainDisplayText":"...3025",
               "imageUrl":"https://az755244.vo.msecnd.net/paymentimages/amex.png",
               "userPaymentSourceId":9758,
               "secondaryDisplayText":"12/27",
               "expDate":"2027-12-31T23:59:59Z",
               "cardIssuer":"Amex"
            }
         ],
         "isSupported":true
      }
   ]
}

my struct looks like this:我的结构如下所示:

struct CreditCard: Codable {
    var authLimit: Int?
    var isCardSupported: Bool?
    var paymentProcessorId: Int?
    var mainDisplayText: String?
    var imageUrl: String?
    var userPaymentSourceId: Int?
    var secondaryDisplayText: String?
    var expDate: String?
    var cardIssuer: String?

    enum CodingKeys: String, CodingKey {
        case cardIssuer = "cardIssuer"
        case authLimit = "authLimit"
        case isCardSupported = "isCardSupported"
        case paymentProcessorId = "paymentProcessorId"
        case mainDisplayText = "mainDisplayText"
        case imageUrl = "imageUrl"
        case userPaymentSourceId = "userPaymentSourceId"
        case secondaryDisplayText = "secondaryDisplayText"
        case expDate = "expDate"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        authLimit = try values.decodeIfPresent(Int.self, forKey: .authLimit)
        isCardSupported = try values.decodeIfPresent(Bool.self, forKey: .isCardSupported)
        paymentProcessorId = try values.decodeIfPresent(Int.self, forKey: .paymentProcessorId)
        mainDisplayText = try values.decodeIfPresent(String.self, forKey: .mainDisplayText)
        imageUrl = try values.decodeIfPresent(String.self, forKey: .imageUrl)
        userPaymentSourceId = try values.decodeIfPresent(Int.self, forKey: .userPaymentSourceId)
        secondaryDisplayText = try values.decodeIfPresent(String.self, forKey: .secondaryDisplayText)
        expDate = try values.decodeIfPresent(String.self, forKey: .expDate)
        cardIssuer = try values.decodeIfPresent(String.self, forKey: .cardIssuer)
    }
}

my json decoder code looks like this:我的 json 解码器代码如下所示:

do {
if let jsonData = response?.responseData {
let jsonDecoder = JSONDecoder()
let creditCards = try jsonDecoder.decode(CreditCard.self, from: jsonData)
print("credit cards \(creditCards)")
completion(nil, creditCards)
}
} catch {
print(error)
}

I'm sure there's probably an obvious oversight to why the model is still all nil.我敢肯定,为什么 model 仍然为零,可能存在明显的疏忽。 Any help would be really appreciated.任何帮助将非常感激。 Thanks!谢谢!

Either decode from the top of the JSON (as @Rob answered) or traverse through the JSON and get the wallets key and then decode it.从 JSON 顶部解码(如@Rob 回答)或遍历 JSON 并获取wallets密钥,然后对其进行解码。

if let jsonData = response?.responseData as? Dictionary<String,Any> {
    if let walletData = jsonData["wallet"] as? [Dictionary<String,Any>] {
        if let mainWalletData = walletData[0]["wallets"] as? [Dictionary<String,Any>] {
            do {
                let jsonDecoder = JSONDecoder()
                let creditCards = try jsonDecoder.decode([CreditCard].self, from: mainWalletData)
                print("credit cards \(creditCards)")
                completion(nil, creditCards)
            }
        } catch {
            print(error)
        }
    }
}
}
struct Wallet: Decodable {
 let wallets: [WalletDetails]
}
struct WalletDetails: Decodable {
 let fundingProviderName: String
 let authLimit: Int
 let pinRequired: Bool
 let wallets: [CreditCard]
}
struct CreditCard: Codable {
var authLimit: Int?
var isCardSupported: Bool?
var paymentProcessorId: Int?
var mainDisplayText: String?
var imageUrl: String?
var userPaymentSourceId: Int?
var secondaryDisplayText: String?
var expDate: String?
var cardIssuer: String?

enum CodingKeys: String, CodingKey {
    case cardIssuer = "cardIssuer"
    case authLimit = "authLimit"
    case isCardSupported = "isCardSupported"
    case paymentProcessorId = "paymentProcessorId"
    case mainDisplayText = "mainDisplayText"
    case imageUrl = "imageUrl"
    case userPaymentSourceId = "userPaymentSourceId"
    case secondaryDisplayText = "secondaryDisplayText"
    case expDate = "expDate"
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    authLimit = try values.decodeIfPresent(Int.self, forKey: .authLimit)
    isCardSupported = try values.decodeIfPresent(Bool.self, forKey: .isCardSupported)
    paymentProcessorId = try values.decodeIfPresent(Int.self, forKey: .paymentProcessorId)
    mainDisplayText = try values.decodeIfPresent(String.self, forKey: .mainDisplayText)
    imageUrl = try values.decodeIfPresent(String.self, forKey: .imageUrl)
    userPaymentSourceId = try values.decodeIfPresent(Int.self, forKey: .userPaymentSourceId)
    secondaryDisplayText = try values.decodeIfPresent(String.self, forKey: .secondaryDisplayText)
    expDate = try values.decodeIfPresent(String.self, forKey: .expDate)
    cardIssuer = try values.decodeIfPresent(String.self, forKey: .cardIssuer)
}
}

You have not added the top level keys and that is why it is not working.您没有添加顶级密钥,这就是它不起作用的原因。 Try this:尝试这个:

 do {
    if let jsonData = response?.responseData {
    let jsonDecoder = JSONDecoder()
    let creditCards = try jsonDecoder.decode(Wallet.self, from: jsonData)
    print("credit cards \(creditCards)")
    completion(nil, creditCards)
    }
    } catch {
    print(error)
    }

top level key wallets is missing in your Codable, and you don't need to implement init(from decoder: Decoder) throws您的 Codable 中缺少顶级密钥wallets ,您不需要实现init(from decoder: Decoder) throws

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM