1

If you wanna test Postman.. You can test on Postman. I couldn't decode data. How can I decode ?

Error:

keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: "data", intValue: nil) ("data").", underlyingError: nil))

enter image description here

Model:

// MARK: - CountryResponse
struct CountryResponse: Codable {
    let countryData: [CountryData]
  
  enum CodingKeys: String, CodingKey {
    case countryData = "data"
  }
}

// MARK: - CountryData
struct CountryData: Codable {
    let code: String
    let currencyCodes: [String]
    let name, wikiDataID: String

    enum CodingKeys: String, CodingKey {
        case code, currencyCodes, name
        case wikiDataID = "wikiDataId"
    }
}

Service:

class CountryService {
    
    func getAllCountry() {
        
        if let url = URL(string: "https://wft-geo-db.p.rapidapi.com/v1/geo/countries?limit=10") {
            var request = URLRequest(url: url)
            request.addValue("wft-geo-db.p.rapidapi.com", forHTTPHeaderField: "x-rapidapi-host")
            request.addValue("api key", forHTTPHeaderField: "x-rapidapi-key")
            request.httpMethod = "GET"
            
            let task = URLSession.shared.dataTask(with: url) { data, response, error in
                guard let data = data else { return }
                
                do {
                    let response = try JSONDecoder().decode(CountryResponse.self, from: data)
                    print("response: \(response)")
                } catch let error {
                    print("data decode edilemedi. \(error)")
                }
                
            }
            task.resume()
        } else {
            print("hatalı url.")
        }
    }
}
Ufuk Köşker
  • 1,288
  • 8
  • 29

2 Answers2

1

This is not the answer to your question, but this is too big for comment, while I think it's important to explain your failure.

It's best to start response handling not from parsing JSON data, but from

  1. Checking whether error is nil. If error is not nil, there's no point to continue with parsing
  2. Check response to make sure response.statusCode is 2xx series (most commonly 200). If it's anything else (e.g. 4xx, 5xx), then the data will probably contain the error received from the server (or nothing at all), but will definitely not contain JSON you expect.

Apple has a good example here:

let task = URLSession.shared.dataTask(with: url) { data, response, error in

    if let error = error {
        // handle error
        return
    } 

    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        // handle the error returned by a server
        return
    }

    // now you are ready to look at the data
    guard let data = data else { return }

    // ...

I think your code will exit either in error or httpResponse condition, and that will explain to you what is failing. Also this is a better practice in general.

timbre timbre
  • 12,648
  • 10
  • 46
  • 77
  • While I agree that the error and the response code should be checked they are about technical errors but the server can still return a json with some error message even when error is nil and the response code is 200. – Joakim Danielson Feb 15 '22 at 07:47
  • @JoakimDanielson so you think I shouldn't have recommended the poster to add the error and HTTP response handling? Or what's your point? – timbre timbre Feb 15 '22 at 14:15
  • Isn't that what I say in the first part of the first sentence? And my point is that the server or rather the API itself might return an error message as a response to the request sent but since this is not a technical error the server (http) will not return an error and the response code will be 200 because for the web server the the request was fine. So there are two possible levels of errors involved here, one for the web server and one for the API running in the web server. – Joakim Danielson Feb 15 '22 at 14:44
  • @JoakimDanielson So you discourage me from providing an improvement to their code which will _likely_ help them solve the issue (which I also started from "This is not the answer to your question"), because there's a probability that this is not going to solve their issue? I am still confused what's the point of your argument... – timbre timbre Feb 15 '22 at 16:05
  • I am only trying to help you improve your answer/advice since I believe it is not complete. I am not sure if you do not want to understand what I am saying or if my English is poor so I am not sure what more to say. – Joakim Danielson Feb 15 '22 at 16:11
1

I received this error. Here is actual error from xcode console.

valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: 
[CodingKeys(stringValue: "result", intValue: nil), _JSONKey(stringValue: 
"Index 152", intValue: 152), CodingKeys(stringValue: "Field", 
intValue: nil)], debugDescription: "Expected String value but found null 
instead.", underlyingError: nil))

The error tells you which element of the array is missing the data and causing the error. In array "Index 152", the value of Field was null, it was a data entry issue. Maybe some of you will have a similar issue as well.

Swift will complain about null values like this when parsing results using a struct.

Mike Volmar
  • 1,927
  • 1
  • 22
  • 31
  • Exactly, this is what happened to me too. This SO, show how to use optionals in your struct to solve it. https://stackoverflow.com/questions/49894198/swift-codable-null-handling – jonathan3087 May 31 '23 at 17:51