I am making an API call with URLSession and I am getting the error like: The data couldn’t be read because it isn’t in the correct format I don't know why it is happeing. Even I am able to print the response in string format but not getting parsed.
API calling method
func getDashboardCountReq() {
guard let url = URL(string: urlString) else {
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "content-type")
let userDetails = UserInfo.shared.getCurrentUserDetails()
if let authToken = userDetails?.authToken {
let headers = ["Content-Type": "application/json",
"Authorization": "Bearer " authToken]
request.allHTTPHeaderFields = headers
}
URLSession.shared.dataTask(with: request) { (data,response,error) in
do {
if let data = data {
let responseString = String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
print("responseString \(responseString)")
do {
let f = try JSONDecoder().decode([DashboardResponseData].self, from: data)
print(f.count)
} catch {
print("1232 \(error.localizedDescription)")
}
} else {
print("LoginViewModel-> no data found")
}
} catch(let error) {
print("Error A123 \(error.localizedDescription)")
}
}.resume()
}
// Model
struct DashboardResponseData: Codable, Identifiable {
let id = UUID()
var approvedrc: String
var pendingpo: String?
var assets: String?
var approvedprs: String?
var pendingrc: String?
var approvedpo: String?
var pendingprs: String?
var tickets: String?
enum CodingKeys: String, CodingKey {
case approvedrc = "approvedrc"
case pendingpo = "pendingpo"
case approvedprs = "approvedprs"
case pendingrc = "pendingrc"
case approvedpo = "approvedpo"
case pendingprs = "pendingprs"
case tickets = "tickets"
}
}
String Response
[{\"approvedrc\":41,\"pendingpo\":566,\"assets\":37956,\"approvedprs\":1040,\"pendingrc\":8,\"approvedpo\":1650,\"pendingprs\":1709,\"tickets\":137872}]
// Log
CodePudding user response:
As mentioned your data are Int
, and you are also missing the assets
in CodingKeys. Try something like this:
struct DashboardResponseData: Codable, Identifiable {
let id = UUID()
let approvedrc, pendingpo, assets, approvedprs: Int?
let pendingrc, approvedpo, pendingprs, tickets: Int?
enum CodingKeys: String, CodingKey {
case approvedrc,pendingpo,assets,approvedprs,pendingrc,approvedpo,pendingprs,tickets
}
}
CodePudding user response:
All the values in DashboardResponseData
are declared as strings, but are integers in the JSON, so you should either parse them as Int
, or add quotes around them in the JSON.
There it works :
import Foundation
let json = "[{\"approvedrc\":41,\"pendingpo\":566,\"assets\":37956,\"approvedprs\":1040,\"pendingrc\":8,\"approvedpo\":1650,\"pendingprs\":1709,\"tickets\":137872}]"
struct DashboardResponseData: Codable, Identifiable {
let id = UUID()
var approvedrc: Int
var pendingpo: Int?
var assets: Int?
var approvedprs: Int?
var pendingrc: Int?
var approvedpo: Int?
var pendingprs: Int?
var tickets: Int?
enum CodingKeys: String, CodingKey {
case approvedrc = "approvedrc"
case pendingpo = "pendingpo"
case approvedprs = "approvedprs"
case pendingrc = "pendingrc"
case approvedpo = "approvedpo"
case pendingprs = "pendingprs"
case tickets = "tickets"
}
}
let f = try JSONDecoder().decode([DashboardResponseData].self, from: json.data(using: .utf8)!)
print(f.count)
Also, note that you can simplify this :
let responseString = String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
which is completely redundant (String.Encoding(rawValue: String.Encoding.utf8.rawValue))
can simply be String.Encoding.utf8
) to this :
let responseString = String(data: data, encoding: .utf8)
because enum type String.Encoding
is deducted as it is the expected type of this argument.