Decoding fails if keys not present. How to safely decode if missing keys also.
I have gone through that use Optional or Nil values but still not able to decoding the objects.
Below my Json
{
"mandatory":true,
"dynamic_obj":[
{
"dt":"2021-09-22 01:29:52",
"url":"https://res._22_01_29.pdf",
"desc":"PAN CARD",
"flag":1,
"count":"2",
"field":"pan_card",
"address":"300-435, Nattu Muthu St, Sheethammal Colony, Venus Colony, Chennai, Tamil Nadu 600018, India",
"visible":true,
"latitude":13.0389309,
"longitude":80.2473746
},
{
"url":"https://res.cloudin/no-image.jpg",
"desc":"driving License",
"count":"2",
"field":"driving_license",
"visible":true
}
]
}
Model class below
struct Dynamic_obj : Codable {
var dt : String?
var url : String?
let desc : String?
var flag : Int?
let count : String?
let field : String?
let visible : Bool?
var bankname : String = "NA"
var pdfPassword : String = "NA"
var latitude : String = "NA"
var longitude : String = "NA"
var address : String = "NA"
enum CodingKeys: String, CodingKey {
case dt = "dt"
case url = "url"
case desc = "desc"
case flag = "flag"
case count = "count"
case field = "field"
case visible = "visible"
case bankname = "bankname"
case pdfPassword = "pdfPassword"
case latitude = "latitude"
case longitude = "longitude"
case address = "address"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
dt = try values.decodeIfPresent(String.self, forKey: .dt)
url = try values.decodeIfPresent(String.self, forKey: .url)
desc = try values.decodeIfPresent(String.self, forKey: .desc)
flag = try values.decodeIfPresent(Int.self, forKey: .flag)
count = try values.decodeIfPresent(String.self, forKey: .count)
field = try values.decodeIfPresent(String.self, forKey: .field)
visible = try values.decodeIfPresent(Bool.self, forKey: .visible)
bankname = try values.decodeIfPresent(String.self, forKey: .bankname) ?? "NA"
pdfPassword = try values.decodeIfPresent(String.self, forKey: .pdfPassword) ?? "NA"
latitude = try values.decodeIfPresent(String.self, forKey: .latitude) ?? "NA"
longitude = try values.decodeIfPresent(String.self, forKey: .longitude) ?? "NA"
address = try values.decodeIfPresent(String.self, forKey: .address) ?? "NA"
}
}
let decoder = JSONDecoder()
do {
let responseModel = try decoder.decode(LoanDocxPending.self, from: data)
if let mandotory = responseModel.mandatory{
self.visibleDocuments["Identity Proof-~id_proof"] = idProof
self.visibleTitle.append("Identity Proof")
}
} catch {
print("error")
}
struct LoanDocxPending :Codable {
let mandatory : Bool?
var dynamic_obj : [Dynamic_obj]?
enum CodingKeys: String, CodingKey {
case mandatory = "mandatory"
case dynamic_obj = "dynamic_obj"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
mandatory = try values.decodeIfPresent(Bool.self, forKey: .mandatory)
dynamic_obj = try values.decodeIfPresent([Dynamic_obj].self, forKey: .dynamic_obj)
}
}
CodePudding user response:
First of all most of your code is not needed, for example the init
methods and almost all CodingKeys.
Second of all as mentioned in the comments rather than printing meaningless literal "error" print the error
instance. It will tell you that latitude
and longitude
are Double
, not String
.
This model matches the JSON in the question
struct DynamicObj : Codable {
let dt : String?
let url, desc : String
let flag : Int?
let count, field : String
let visible : Bool
var bankname, pdfPassword, address : String?
var latitude, longitude : Double?
}
struct LoanDocxPending :Codable {
let mandatory : Bool
var dynamicObj : [DynamicObj]
enum CodingKeys: String, CodingKey {
case mandatory,dynamicObj = "dynamic_obj"
}
}
let decoder = JSONDecoder()
do {
let responseModel = try decoder.decode(LoanDocxPending.self, from: data)
print(responseModel.mandatory)
} catch {
print("error", error)
}