使用解码协议解析Json(可编码)

问题描述 投票:0回答:1

我正在尝试使用Codable协议解析JSON,但出现异常。此异常是由于响应为null值而导致第二个响应为哪个nestedkeyedcontainer。

对于下面的json响应,它可以正常工作

    let jsonStr = """
   {
     "response": {
         "PURCHASE_FREE_SIM_RESPONSE": {
                                "TOPUP": null,
                                "TOTAL_PAYMENT_AMOUNT": "0",
                                "TRANSACTION_ID": "MFST0000233010",
                                "TAX": null,
                                "VAT": null,
                                "SHIPPING_AMOUNT": null,
                                "ITG_TRANSACTION_ID": "ITG000000138832750",
                                "CHANNEL_TRANSACTION_ID": "8e56ecf01b",
                                "PAYMENT_RESPONSE": null,
                                "APM_RESPONSE": null,
                                 "APPLICATION_TYPE": null,
                                 "NAME_OR_PAGE_ID": null,
                                 "URL": null,
                                 "CUSTOM_FIELD_1": null,
                                 "CUSTOM_FIELD_2": null,
                                 "CUSTOM_FIELD_3": null,
                                 "FEE": null
                  }
         },
     "API-Code": "engbr_mvnepurchasefreesim",
     "statuscode": 200,
     "statusMessage": "SUCCESS",
     "respCode": {
     "ERROR_CODE": "0",
     "ERROR_DESC": "Success"
      }
     }
    """
    //=========Second Response===============

        let jsonStr = """
         {
            **"response": null,**
            "API-Code": null,
            "statuscode": 500,
            "statusMessage": "Undefined index: HOUSE_NO",
              **"respCode": null**
           }

        """

我的模特看起来像:-

struct SimPurResponse:Decodable{
let topUp:String
let totalPaymentAmt:String
let transId:String
let tax:String
let vat:String
let shipingAmt:String
let itgTransId:String
let chanelTransId:String
let paymentResponse:String
let apmResponse:String
let applicationType:String
let nameorPageId:String
let url:String
let customField1:String
let customField2:String
let customField3:String
let fee:String

let apiCode:String
let statuscode:Int
let statusMessage:String

let errorCode:String
let errorDesc:String


private enum ResponseOuter : String, CodingKey {
    case response
    case apiCode      = "API-Code"
    case statuscode   = "statuscode"
    case respCode
    case statusMessage = "statusMessage"
}

enum RespCodeKeys : String, CodingKey {
    case errorCode   = "ERROR_CODE"
    case errorDesc   = "ERROR_DESC"
}

private enum Response : String, CodingKey {
    case PURCHASE_FREE_SIM_RESPONSE
}

private enum purchaseFreeSimResInfo : String, CodingKey {
    case topUp            = "TOPUP"
    case totalPaymentAmt  = "TOTAL_PAYMENT_AMOUNT"
    case transId          = "TRANSACTION_ID"
    case tax              = "TAX"
    case vat              =  "VAT"
    case shipingAmt       = "SHIPPING_AMOUNT"
    case itgTransId       = "ITG_TRANSACTION_ID"
    case chanelTransId    = "CHANNEL_TRANSACTION_ID"
    case paymentResponse  = "PAYMENT_RESPONSE"
    case apmResponse      = "APM_RESPONSE"
    case applicationType  = "APPLICATION_TYPE"
    case nameorPageId     = "NAME_OR_PAGE_ID"
    case url              = "URL"
    case customField1     = "CUSTOM_FIELD_1"
    case customField2     = "CUSTOM_FIELD_2"
    case customField3     = "CUSTOM_FIELD_3"
    case fee              = "FEE"
}


init(from decoder :Decoder) throws {
    let container     = try decoder.container(keyedBy: ResponseOuter.self)
    self.apiCode      = try container.decodeIfPresent(String.self, forKey: .apiCode) ?? ""
    self.statuscode    = try container.decodeIfPresent(Int.self, forKey: .statuscode) ?? 600
    self.statusMessage = try container.decodeIfPresent(String.self, forKey: .statusMessage) ?? ""

    let respCodeCont =  try container.nestedContainer(keyedBy: RespCodeKeys.self, forKey: .respCode)
    self.errorCode   =  try respCodeCont.decodeIfPresent(String.self, forKey: .errorCode) ?? ""
    self.errorDesc   =  try respCodeCont.decodeIfPresent(String.self, forKey: .errorDesc) ?? ""


    let purcCont          = try container.nestedContainer(keyedBy: Response.self, forKey: .response)
    let purSimCont        = try purcCont.nestedContainer(keyedBy: purchaseFreeSimResInfo.self, forKey: .PURCHASE_FREE_SIM_RESPONSE)
    self.topUp            = try purSimCont.decodeIfPresent(String.self, forKey: .topUp) ?? ""
    self.totalPaymentAmt    = try purSimCont.decodeIfPresent(String.self, forKey: .totalPaymentAmt) ?? ""
    self.transId           = try purSimCont.decodeIfPresent(String.self, forKey: .transId) ?? ""
    self.tax              = try purSimCont.decodeIfPresent(String.self, forKey: .tax) ?? ""
    self.vat               = try purSimCont.decodeIfPresent(String.self, forKey: .vat) ?? ""
    self.shipingAmt       = try purSimCont.decodeIfPresent(String.self, forKey: .shipingAmt) ?? ""

    self.itgTransId          = try purSimCont.decodeIfPresent(String.self, forKey: .itgTransId) ?? ""
    self.chanelTransId       = try purSimCont.decodeIfPresent(String.self, forKey: .chanelTransId) ?? ""
    self.paymentResponse     = try purSimCont.decodeIfPresent(String.self, forKey: .paymentResponse) ?? ""
    self.apmResponse        = try purSimCont.decodeIfPresent(String.self, forKey: .apmResponse) ?? ""
    self.applicationType    = try purSimCont.decodeIfPresent(String.self, forKey: .applicationType) ?? ""
    self.nameorPageId       = try purSimCont.decodeIfPresent(String.self, forKey: .nameorPageId) ?? ""
    self.url                = try purSimCont.decodeIfPresent(String.self, forKey: .url) ?? ""

    self.customField1       = try purSimCont.decodeIfPresent(String.self, forKey: .customField1) ?? ""
    self.customField2       = try purSimCont.decodeIfPresent(String.self, forKey: .customField2) ?? ""
    self.customField3       = try purSimCont.decodeIfPresent(String.self, forKey: .customField3) ?? ""
    self.fee                 = try purSimCont.decodeIfPresent(String.self, forKey: .fee) ?? ""
}

}

        let dataJosn = Data(jsonStr.utf8)

 do {
     let simDetail = try JSONDecoder().decode(SimPurResponse.self, from: dataJosn)

   print(simDetail)


    }catch let error {
      print(error)
    }

我在处理这两种情况时遇到问题。上面完整的代码

swift encode codable decodable
1个回答
0
投票

只需将您的“尝试”更改为“尝试?”在访问解码器初始化程序块中的nestedContainer时,并在需要的地方添加可选的链接:

init(from decoder :Decoder) throws {

    let data = try decoder.container(keyedBy: ResponseOuter.self)

    self.apiCode      = try data.decodeIfPresent(String.self, forKey: .apiCode) ?? ""
    self.statuscode    = try data.decodeIfPresent(Int.self, forKey: .statuscode) ?? 600
    self.statusMessage = try data.decodeIfPresent(String.self, forKey: .statusMessage) ?? ""

    let respCodeCont =  try? data.nestedContainer(keyedBy: RespCodeKeys.self, forKey: .respCode)
    self.errorCode   =  try respCodeCont?.decodeIfPresent(String.self, forKey: .errorCode) ?? ""
    self.errorDesc   =  try respCodeCont?.decodeIfPresent(String.self, forKey: .errorDesc) ?? ""

    let purcCont          = try? data.nestedContainer(keyedBy: Response.self, forKey: .response)
    let purSimCont        = try purcCont?.nestedContainer(keyedBy: purchaseFreeSimResInfo.self, forKey: .PURCHASE_FREE_SIM_RESPONSE)
    self.topUp            = try purSimCont?.decodeIfPresent(String.self, forKey: .topUp) ?? ""
    self.totalPaymentAmt    = try purSimCont?.decodeIfPresent(String.self, forKey: .totalPaymentAmt) ?? ""
    self.transId           = try purSimCont?.decodeIfPresent(String.self, forKey: .transId) ?? ""
    self.tax              = try purSimCont?.decodeIfPresent(String.self, forKey: .tax) ?? ""
    self.vat               = try purSimCont?.decodeIfPresent(String.self, forKey: .vat) ?? ""
    self.shipingAmt       = try purSimCont?.decodeIfPresent(String.self, forKey: .shipingAmt) ?? ""

    self.itgTransId          = try purSimCont?.decodeIfPresent(String.self, forKey: .itgTransId) ?? ""
    self.chanelTransId       = try purSimCont?.decodeIfPresent(String.self, forKey: .chanelTransId) ?? ""
    self.paymentResponse     = try purSimCont?.decodeIfPresent(String.self, forKey: .paymentResponse) ?? ""
    self.apmResponse        = try purSimCont?.decodeIfPresent(String.self, forKey: .apmResponse) ?? ""
    self.applicationType    = try purSimCont?.decodeIfPresent(String.self, forKey: .applicationType) ?? ""
    self.nameorPageId       = try purSimCont?.decodeIfPresent(String.self, forKey: .nameorPageId) ?? ""
    self.url                = try purSimCont?.decodeIfPresent(String.self, forKey: .url) ?? ""

    self.customField1       = try purSimCont?.decodeIfPresent(String.self, forKey: .customField1) ?? ""
    self.customField2       = try purSimCont?.decodeIfPresent(String.self, forKey: .customField2) ?? ""
    self.customField3       = try purSimCont?.decodeIfPresent(String.self, forKey: .customField3) ?? ""
    self.fee                 = try purSimCont?.decodeIfPresent(String.self, forKey: .fee) ?? ""
}

希望这会有所帮助。干杯。

© www.soinside.com 2019 - 2024. All rights reserved.