I have a simple array that I want to decode. I can deal with arrays in a JSON format with creating a new struct in the model class, and attributing that struct as an array in the main struct. But in this case, the json data is already on an array with 1 element. Therefore I should get the first element in the json response. I think I need to provide a decoder before I can access anything, but I don't know how that decoder model should be. The error I'm getting is:
typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
JSON data I want to decode: (notice the data is on a array)
[
{
"name": "United States",
"topLevelDomain": [
".us"
],
"alpha2Code": "US",
"alpha3Code": "USA",
"callingCodes": [
"1"
],
"capital": "Washington, D.C.",
"altSpellings": [
"US",
"USA",
"United States of America"
],
"region": "Americas",
"subregion": "Northern America",
"population": 321645000,
"latlng": [
38,
-97
],
"demonym": "American",
"area": 9629091,
"gini": 48,
"timezones": [
"UTC-12:00",
"UTC-11:00",
"UTC-10:00",
"UTC-09:00",
"UTC-08:00",
"UTC-07:00",
"UTC-06:00",
"UTC-05:00",
"UTC-04:00",
"UTC+10:00",
"UTC+12:00"
],
"borders": [
"CAN",
"MEX"
],
"nativeName": "United States",
"numericCode": "840",
"currencies": [
"USD",
"USN",
"USS"
],
"languages": [
"en"
],
"translations": {
"de": "Vereinigte Staaten von Amerika",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"it": "Stati Uniti D'America"
},
"relevance": "3.5"
} ]
model class:
struct CountryModel: Codable {
let country: [MyResponse]
}
struct MyResponse: Codable {
let name: String
let capital: String
}
Manager class:
struct CountryManager {
let countryURL = "https://restcountries-v1.p.rapidapi.com/name/"
func fetchData(_ countryName: String) {
let urlString = "\(countryURL)\(countryName)"
print(urlString)
performRequest(urlString)
}
func performRequest(_ urlString: String){
if let url = URL(string: urlString){
var request = URLRequest(url:url)
request.setValue("x-rapidapi-key", forHTTPHeaderField: "myapikey")
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request) { (data, response, error) in
if let e = error {
print(e)
return
}
if let safeData = data {
self.parseJSON(safeData)
}
}
task.resume()
}
}
func parseJSON(_ countryData: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode([CountryModel].self, from: countryData)
print(decodedData[0].country)
}
catch {
print(error)
}
}
}
Most of the fields are missing from your model. Here is how it should look like instead:
struct Country: Codable {
let name: String
let topLevelDomains: [String]
let alpha2Code: String
let alpha3Code: String
let callingCodes: [String]
let capital: String
let altSpellings: [String]
let region: String
let subregion: String
let population: Int
let latlng: [Int]
let demonym: String
let area: Int
let gini: Int
let timezones: [String]
let borders: [String]
let nativeName: String
let numericCode: String
let currencies: [String]
let languages: [String]
let translation: Translation
let relevance: String
}
struct Translation: Codable {
let de: String
let es: String
let fr: String
let ja: String
let it: String
}
I found out that there was a problem in my http request. I used Alamofire in the request part and I don't experience the problem anymore. The issue seemed to be related to the decoding but I don't know. I'm posting the final code if anyone experiences the same issue.
import Foundation
import Alamofire
struct CountryManager {
let countryURL = "https://restcountries-v1.p.rapidapi.com/name/"
func fetchData(_ countryName: String) {
let urlString = "\(countryURL)\(countryName)"
print(urlString)
performRequest(urlString)
}
func performRequest(_ urlString: String){
let headers: HTTPHeaders = [
"x-rapidapi-host": "restcountries-v1.p.rapidapi.com",
"x-rapidapi-key": "apices"
]
AF.request(urlString, headers: headers).responseJSON { response in
self.parseJSON(response.data!)
}
}
func parseJSON(_ countryData: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(CountryAlias.self, from: countryData)
print(decodedData[0].name)
}
catch {
print(error)
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.