如何在 swift 中将 JSON `null` 值传递给`nil` 值?
Posted
技术标签:
【中文标题】如何在 swift 中将 JSON `null` 值传递给`nil` 值?【英文标题】:How to pass JSON `null` value to `nil` value in swift? 【发布时间】:2019-08-02 03:42:01 【问题描述】:我有这个json
,其中hospitalNumber
有值,并且有实例返回null
值。 hospitalNumber
具有重要意义,因为它是 API 中端点所需参数的一部分。请看样例json
:
"responseMessage": "Request successful",
"data": [
"hospitalNumber": null,
"patientName": "Manual Entry",
"totalAmount": 10339.8000,
"manualEntry": true
,
"hospitalNumber": "1111111",
"patientName": "test patient",
"totalAmount": 932.5000,
"manualEntry": false
]
下面是我的 APIService,它将拉取上面的 json
。
typealias getPatientDetailsPerPayoutTaskCompletion = (_ patientDetailsPerPayout: [PatientPayoutDetails]?, _ error: NetworkError?) -> Void
//Patient procedure details per patient
//parameterName is .searchByHospitalNumber = "hospitalNumber"
static func getPatientDetailsPerPayout(periodId: Int, doctorNumber: String, parameterName: PatientParameter, hospitalNumber: String, manualEntry: Bool, completion: @escaping getPatientDetailsPerPayoutTaskCompletion)
guard let patientDetailsPerPayoutURL = URL(string: "\(Endpoint.Patient.patientProcedureDetails)?periodId=\(periodId)&doctorNumber=\(doctorNumber)\(parameterName.rawValue)\(hospitalNumber)&manualEntry=\(manualEntry)") else
completion(nil, .invalidURL)
return
let sessionManager = Alamofire.SessionManager.default
sessionManager.session.getAllTasks (tasks) in
tasks.forEach( $0.cancel() )
Alamofire.request(patientDetailsPerPayoutURL, method: .get, encoding: JSONEncoding.default).responseJSON (response) in
print(patientDetailsPerPayoutURL)
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)
return
let decoder = JSONDecoder()
do
let patientDetailsPayout = try decoder.decode(RootPatientPayoutDetails.self, from: jsonData)
if (patientDetailsPayout.data?.isEmpty)!
completion(nil, .noRecordFound)
else
completion(patientDetailsPayout.data, nil)
catch
completion(nil, .invalidJSON)
case 400: completion(nil, .badRequest)
case 404: completion(nil, .noRecordFound)
default:
print("**UNCAPTURED STATUS CODE FROM (getPatientDetailsPayout)\nSTATUS CODE: \(statusCode)")
completion(nil, .uncapturedStatusCode)
getPatientPayoutDetails 函数
func getPerPatientPayoutDetails(from: String, manualEntry: Bool)
//SVProgressHUD.setDefaultMaskType(.black)
//SVProgressHUD.setForegroundColor(.white)
SVProgressHUD.setBackgroundColor(.lightGray)
SVProgressHUD.show(withStatus: "Retrieving Patient Procedures")
APIService.PatientList.getPatientDetailsPerPayout(periodId: doctorPayoutWeek[3].periodId!, doctorNumber: doctorNumber, parameterName: .selectedByHospitalNumber, hospitalNumber: from, manualEntry: manualEntry) (patientPayout, error) in
guard let patientPerPayoutDetails = patientPayout, 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))
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)
SVProgressHUD.dismiss()
return
self.selectedPatientPayment = patientPerPayoutDetails
print(self.selectedPatientPayment)
SVProgressHUD.dismiss()
return
表格视图
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
switch indexPath.section
case 0: break
case 1: break
case 2:
filteredPatient = indexPath.row
let selectedpatient = patientList[filteredPatient].hospitalNumber
let selectedEntry = patientList[filteredPatient].manualEntry
self.isBrowseAll = false
getPerPatientPayoutDetails(from: selectedpatient!, manualEntry: selectedEntry)
default: break
hospitalNumber
为 nil 时需要 null
字符串的端点
https://sample.com/openapi/getpatientpayoutdetails?periodId=579&doctorNumber=2866&hospitalNumber=null&manualEntry=true
如您所见,医院编号对于端点具有重要作用。我的问题是,一旦 tableView
重新加载它会正确显示数据,但是当我 didSelect
cell
和 null
hospitalNumber 时,我的应用程序崩溃并显示 Found nil error 自 @987654338 @ 具有 null
值。希望您理解我要解释的内容,请帮助我。谢谢你
【问题讨论】:
如果您不确定是否会获得某个键的确定值,请在您的Codable
模型中将该变量设置为 optional
。和don't force unwrap
,使用guard-let/if-let
。
@SharadChauhan 我有这个 `struct Patient: Codable var hospitalNumber: String? var 患者姓名:字符串? var totalAmount: Double var manualEntry: Bool enum CodingKeys: String, CodingKey case hospitalNumber = “hospitalNumber” case patientName = “patientName” case totalAmount = “totalAmount” case manualEntry = “manualEntry”
如果 hospitalNumber 是 nil
,预期的行为是什么?顺便说一句,didSelect
中的switch
太过分了。只需检查if indexPath.section == 2 filteredPatient = indexPath.row ...
@vadian 如果hospitalNumber
是nil
。它应该返回null
值。因为端点应该是这样的https://sample.com/openapi/getpatientpayoutdetails?periodId=579&doctorNumber=2866&hospitalNumber=null&manualEntry=true
【参考方案1】:
您的Codable
模型是正确的,您只需要guard-let/if-let
即可防止崩溃:
if let selectedpatient = patientList[filteredPatient].hospitalNumber, let selectedEntry = patientList[filteredPatient].manualEntry
self.isBrowseAll = false
getPerPatientPayoutDetails(from: selectedpatient, manualEntry: selectedEntry)
更新:
如果你想在 nil 的情况下创建 endPoint
也可以使用 coalescing operator
:
getPerPatientPayoutDetails(from: selectedpatient ?? "null", manualEntry: selectedEntry)
【讨论】:
我试过你的答案,我的应用程序没有崩溃,但是当我打印manualEntryFlag
的值时,为什么值从true
更改为false
。哪个是我应该得到参数的实际值
没有代码可以更改manualEntryFlag
的值,所以您可能需要再次正确地检查该值。【参考方案2】:
在 didSelect 中做喜欢
let selectedpatient:String! //or Int whatever type it is right not this line initializes selected patient with nil
//below line will check for nil and ALSO NULL if NULL or nil it will not reassigne selectedpatient which means selectedpatient will remain nil
if let hsptlNbr = patientList[filteredPatient].hospitalNumber as? yourDataType
selectedpatient = hsptlNbr
在此之后,如果在下面的方法中存在,您可以将其作为 nil 或值传递
getPerPatientPayoutDetails(from: selectedpatient, manualEntry: selectedEntry)
更改func getPerPatientPayoutDetails(from: String, manualEntry: Bool)
到
func getPerPatientPayoutDetails(from: String?, manualEntry: Bool)
【讨论】:
您的意思是String?
?因为情况正好相反。如果不设置值,这段代码会崩溃。
@titus 设置 getPerPatientPayoutDetails(from: String? from as optional :) 不会崩溃
或者是的,他可以用作 let selectedpatient:String?
它会崩溃。当您使用 !
隐式展开一个值时。你告诉编译器它不是nil
。所以当你尝试阅读它时,如果它是nil
,它会崩溃。以上是关于如何在 swift 中将 JSON `null` 值传递给`nil` 值?的主要内容,如果未能解决你的问题,请参考以下文章