[英]How to fix invalid JSON response in swift when using get request in Alamofire?
我正在創建一個應用程序,其中它從API Server中提取PatientList
,並將其顯示到TableView
。 經過檢查后,它返回200
狀態代碼,但落入invalidJSON
錯誤。 但是當我簽入Postman時 ,它返回200
狀態代碼並正確提取記錄。 我很困惑我的代碼的哪一部分會導致錯誤,因為我是新手。 我正在尋求幫助以解決該問題。 以下是我的示例代碼供您參考。 提前非常感謝您。
Patient.swift
struct Patient: Codable {
let hospitalNumber: Int
let patientName: String
let totalAmount: Double
enum CodingKeys: String, CodingKey {
case hospitalNumber = "hospitalNumber"
case patientName = "patientName"
case totalAmount = "totalAmount"
}
}
APIService.swift
struct PatientList {
typealias getPatientListTaskCompletion = (_ patientListperPayout: [Patient]?, _ error: NetworkError?) -> Void
static func getPatientList(doctorNumber: Int, periodId: Int, completion: @escaping getPatientListTaskCompletion) {
guard let patientPerPayoutURL = URL(string: "\(Endpoint.Patient.patientPerPayout)?periodId=\(periodId)&doctorNumber=\(doctorNumber)") else {
completion(nil, .invalidURL)
return
}
let sessionManager = Alamofire.SessionManager.default
sessionManager.session.getAllTasks { (tasks) in
tasks.forEach({ $0.cancel() })
}
Alamofire.request(patientPerPayoutURL, method: .get, encoding: JSONEncoding.default).responseJSON { (response) in
guard HelperMethods.reachability(responseResult: response.result) else {
completion(nil, .noNetwork)
return
}
guard let statusCode = response.response?.statusCode else {
completion(nil, .noStatusCode)
return
}
switch(statusCode) {
case 200:
guard let jsonData = response.data else{
completion(nil, .invalidJSON)
print(statusCode)
return
}
let decoder = JSONDecoder()
do {
let patientListArray = try decoder.decode([Patient].self, from: jsonData)
let sortedPatientListArray = patientListArray.sorted(by: { $0.patientName < $1.patientName })
completion(sortedPatientListArray, nil)
}catch{
completion(nil, .invalidJSON)
print(statusCode)
}
case 400:
completion(nil, .badRequest)
case 404:
completion(nil, .noRecordFound)
default:
print("UNCAPTURED STATUS CODE FROM getPatientList\nSTATUS CODE: \(statusCode)")
completion(nil, .uncapturedStatusCode)
}
}
}
Controller.swift
var patientList: [Patient]! {
didSet {
performSegue(withIdentifier: patientListIdentifier, sender: self)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.latestCreditedAmountTableView.dataSource = self
self.latestCreditedAmountTableView.delegate = self
configureTableViewCell()
showTotalCreditedAmount()
getDoctorPayoutSummary(doctorNumber: doctorNumber)
}
func getDoctorPayoutSummary(doctorNumber: Int) {
self.payoutSummary = payoutSummaryDetails
self.taxRateVatRateLabel.text = "\(self.payoutSummary.taxRate) / \(self.payoutSummary.vatRate)"
self.getPatientList()
self.latestCreditedAmountTableView.reloadData()
return
}
func getPatientList() {
APIService.PatientList.getPatientList(doctorNumber: doctorNumber, periodId: currentRemittance.periodId) { (patientListArray, error) in
guard let patientListPerPayout = patientListArray, error == nil else {
if let networkError = error {
switch networkError {
case .noRecordFound:
let alertController = UIAlertController(title: "No Record Found", message: "You don't have current payment remittance", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
case .noNetwork:
let alertController = UIAlertController(title: "No Network", message: "\(networkError.rawValue)", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
default:
let alertController = UIAlertController(title: "Error", message: "There is something went wrong. Please try again", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true, completion: nil)
}
}
return
}
self.patientList = patientListPerPayout
return
}
}
JSON回應
[
{
"hospitalNumber": null,
"patientName": null,
"totalAmount": 31104
},
{
"hospitalNumber": "",
"patientName": "LastName, FirstName",
"totalAmount": 3439.8
}
]
您的JSON響應顯示,某些字段可以為空-至少hospitalNumber
和patientName
。 此外, hospitalNumber
是JSON中的字符串-感謝@Don指出。 您的struct
還應該能夠通過使映射字段也可以為空來應對這些可為空的情況。 即
struct Patient: Codable {
let hospitalNumber: String?
let patientName: String?
let totalAmount: Double
enum CodingKeys: String, CodingKey {
case hospitalNumber = "hospitalNumber"
case patientName = "patientName"
case totalAmount = "totalAmount"
}
}
如果totalAmount
也可以為null,則需要執行相同的totalAmount
。 當然,在任何情況下API是否正確返回空值都是另一個問題-可能需要解決空醫院號或醫院名稱如何有用的問題。
確保在使用它們時不要強行拆開它們。
只需在模型類中進行以下更改。 將模型類變量定義為optional
,這不是API所必需的。
struct Patient: Codable {
var hospitalNumber: String?
let patientName: String?
let totalAmount: Double?
enum CodingKeys: String, CodingKey {
case hospitalNumber = "hospitalNumber"
case patientName = "patientName"
case totalAmount = "totalAmount"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let hospitalNumb = try container.decode(Int?.self, forKey: .hospitalNumber) {
hospitalNumber = String(hospitalNumb)
} else {
hospitalNumber = try container.decode(String.self, forKey: .hospitalNumber)
}
patientName = try container.decode(String.self, forKey: .patientName)
totalAmount = try container.decode(Double.self, forKey: .totalAmount)
}
}
注意:
如果相同密鑰的類型不同,或者您可以說該類型不同於指定的類型,則Codable
OR Decodable
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.