如何快速将JSON`null`值传递给`nil`值?

时间:2019-08-02 03:42:01

标签: ios json swift alamofire

我有这个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
    }
}

tableView

 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
    }
}

在端点null为零时需要hospitalNumber字符串的端点

https://sample.com/openapi/getpatientpayoutdetails?periodId=579&doctorNumber=2866&hospitalNumber=null&manualEntry=true

如您所见,医院号码对于端点起着重要作用。我的问题是,tableView重新加载后,它可以正确显示数据,但是当我didSelectcell医院编号null一起使用时,我的应用程序崩溃并显示 Found nil错误,因为hospitalNumber的值为null。希望您理解我要解释的内容,请帮助我。谢谢

2 个答案:

答案 0 :(得分:0)

您的Codable模型是正确的,您只需要guard-let/if-let即可防止崩溃:

if let selectedpatient = patientList[filteredPatient].hospitalNumber, let selectedEntry = patientList[filteredPatient].manualEntry {
   self.isBrowseAll = false
   getPerPatientPayoutDetails(from: selectedpatient, manualEntry: selectedEntry)
}

更新: 如果您还想创建endPoint(如果为nil的话),则也可以使用coalescing operator

getPerPatientPayoutDetails(from: selectedpatient ?? "null", manualEntry: selectedEntry)

答案 1 :(得分:0)

在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)