为啥我的 json 响应对象返回 nil?
Posted
技术标签:
【中文标题】为啥我的 json 响应对象返回 nil?【英文标题】:Why are my json response objects returning nil?为什么我的 json 响应对象返回 nil? 【发布时间】:2020-06-11 04:52:29 【问题描述】:我有一些 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
]
我的结构是这样的:
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)
我的 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)
我敢肯定,为什么模型仍然为零,这可能是一个明显的疏忽。任何帮助将非常感激。谢谢!
【问题讨论】:
您必须始终从顶部解码 JSON。因此,两个带有键wallets
的对象(顺便说一下是数组)都丢失了。而且你不需要所有的样板初始化代码。字典清楚地总是包含所有键。
您的 Codable 中缺少***密钥 "wallets":
,请检查并更新
你可以按照这个教程youtube.com/watch?v=cyWrj61vpCY我想这对你有帮助!
【参考方案1】:
要么从 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)
【讨论】:
【参考方案2】: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)
您没有添加***密钥,这就是它不起作用的原因。试试这个:
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)
【讨论】:
【参考方案3】:您的 Codable 中缺少***密钥 wallets
,您无需实现
init(from decoder: Decoder) throws
【讨论】:
以上是关于为啥我的 json 响应对象返回 nil?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能用我的 api 响应更新我的状态?数据是一个对象数组
为啥在测试 RSPEC 时 JBuilder 不返回 JSON 中的响应正文