Search code examples
swiftuixcode11swift5type-mismatchurlsession

SwiftUI URLSession error when fetching data (typeMismatch) WEBAPI


Im trying to fetch data from a url once ive pressed a button and called for the function but once the function is called i keep getting a typeMismatch error.

This is my code:

struct User: Decodable {
    var symbol: String
    var price: Double
}

struct Response: Decodable {
    var results:[User]
}


struct ContentView: View {
    var body: some View {
        VStack {
            Text("hello")
            Button(action: {
                self.fetchUsers(amount: 0)
            }) {
                Text("Button")
            }
        }

    }

    func fetchUsers(amount: Int) {
        let url:URL = URL(string: "https://api.binance.com/api/v3/ticker/price")!

        URLSession.shared.dataTask(with: url) { (data, res, err) in
            if let err = err { print(err) }
            guard let data = data else { return }
            do {
                let response = try JSONDecoder().decode(Response.self, from: data)
                print(response.results[0])
            } catch let err {
                print(err)
            }
        }.resume()
    }

}

This is the error:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))

The website url where im trying to fetch data from is: https://api.binance.com/api/v3/ticker/price

enter image description here Im trying to fetch a specific price from a specific symbol for example the price of ETHBTC, which would be 0.019...

Thank you


Solution

  • There are two mistake in this approach. First of all, if you created a Response struct with

    results = [User]
    

    this way you expect the json to be in the form of [result: {}] but you have [{}] format without a name at the beginging. So you should replace the response struct with

    typealias Response = [User]
    

    Second of all the API you are using is returning string instead of double as a price, so you should modify your struct to this:

    struct User: Decodable {
        var symbol: String
        var price: String
    }
    

    This way it worked for me. Tested under

    • swift 5
    • xcode 11.3.1
    • iOS 13.3.1 non beta