'"Expected to decode Dictionary<String, Any> but found an array instead." Cannot seem to fix
I am creating an app which uses an external API to fetch JSON data. I keep getting the error above and I cannot figure out how to fix it. As you can see, I have tried making all the struct values optional and it still fails.
Here is my JSON data
[
{
"user_id": 433354,
"property_id": 334528,
"room_type_id": 399936,
"periods": [
{
"start": "0001-01-01",
"end": "0001-01-01",
"available": 1,
"closed_period": null,
"bookings": [],
"channel_calendars": []
}
]
}
]
Here is the model (I checked all the data types with the API documentation)
import Foundation
struct closed_period: Codable {
var id: Int?
}
struct bookings: Codable {
var id: Int?
var status: String?
}
struct channel_calendars: Codable {
var id: Int?
}
struct periods: Codable {
var start: String?
var end: String?
var available: Int?
var closed_period: closed_period?
var bookings: [bookings]?
var channel_calendars: [channel_calendars]?
}
struct Info: Codable {
var user_id: Int?
var property_id: Int?
var room_type_id: Int?
var periods: [periods]?
}
struct APIResults: Codable {
var decodedResults: [Info]?
}
And this is the code that attempts to decode the JSON
let headers: HTTPHeaders = [
"Accept": "application/json",
"X-ApiKey": "{API Key}"
]
AF.request("{API URL}", headers: headers).responseJSON { response in
if let data = response.data {
let json = String(data: data, encoding: .utf8)
print("Response: \(json!)")
let jsonData = json?.data(using: .utf8)!
let jsonDecoded = try! JSONDecoder().decode(APIResults.self, from: jsonData!)
print(jsonDecoded)
}
}
Finally, this is the console error I receive
2022-03-02 20:48:15.271752+0000 JSONDecoding[5621:1368607]
JSONDecoding/ContentView.swift:29: Fatal error: 'try!' expression
unexpectedly raised an error: Swift.DecodingError.typeMismatch(
Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(
codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any>
but found an array instead.", underlyingError: nil))
Any help is greatly appreciated as I can't figure out the issue and this app is a project that I need to submit! Thanks everyone!
Solution 1:[1]
@Joakim answer's is right, APIResults should be deleted and you should use directly your Info struct:
See working example: https://swiftfiddle.com/kzopdsydabd7rdvyue4azstqbm
import Foundation
var json: [String : Any] = [
"user_id": 433354,
"property_id": 334528,
"room_type_id": 399936,
"periods": [ [
"start": "0001-01-01",
"end": "0001-01-01",
"available": 1,
"closed_period": nil,
"bookings": [],
"channel_calendars": []
]
]
]
struct closed_period: Codable {
var id: Int?
}
struct bookings: Codable {
var id: Int?
var status: String?
}
struct channel_calendars: Codable {
var id: Int?
}
struct periods: Codable {
var start: String?
var end: String?
var available: Int?
var closed_period: closed_period?
var bookings: [bookings]?
var channel_calendars: [channel_calendars]?
}
struct Info: Codable {
var user_id: Int?
var property_id: Int?
var room_type_id: Int?
var periods: [periods]?
}
struct APIResults: Codable {
var decodedResults: [Info]?
}
extension Dictionary {
/// Convert Dictionary to JSON string
/// - Throws: exception if dictionary cannot be converted to JSON data or when data cannot be converted to UTF8 string
/// - Returns: JSON string
func toJson() throws -> String {
let data = try JSONSerialization.data(withJSONObject: self)
if let string = String(data: data, encoding: .utf8) {
return string
}
throw NSError(domain: "Dictionary", code: 1, userInfo: ["message": "Data cannot be converted to .utf8 string"])
}
}
let jsonString = try json.toJson()
let jsonData = try JSONSerialization.data(withJSONObject: json)
do {
let results: Info = try JSONDecoder().decode(Info.self, from: jsonData)
print(results)
} catch {
print(error)
}
Your example use an array of Info object so yes, again use [Info].self in the decode method (in mine it decode only one Info object).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
