0

i have no experience with creating apps in swift but please bear with us. I would like to get data from public API in JSON format and create struct in swift, so i've found some tutorials but i' am facing issues.

I'm pretty sure that api returns json values, i've tested it via

let dataAsString = String(data: data, encoding: .utf8)

and i've got correct response.

But when i try to make objects from this response

let stations = try JSONDecoder().decode([Station].self, from: data)
                print(stations) // returns nil

It prints this error:

//Error:  typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "gegrLat", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil))

All of my code with data structures:

import UIKit

struct Commune: Codable{
    var communeName: String
    var districtName: String
    var proviceName: String
}

struct City: Codable{
    var id: Int
    var name: String
    var commune: Commune
}

struct Station: Codable {
    var id: Int
    var stationName: String
    var gegrLat: Double
    var gegrLon: Double
    var city: City
    var addressStreet: String?
}

class SearchViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let searchController = UISearchController(searchResultsController: nil)
        self.navigationItem.searchController = searchController

        let jsonUrlString = "http://api.gios.gov.pl/pjp-api/rest/station/findAll"
        guard let url = URL(string: jsonUrlString) else { return }

        URLSession.shared.dataTask(with: url){ (data, response, error) in
            guard let data = data else { return }
            //let dataAsString = String(data: data, encoding: .utf8)
            //print(dataAsString) //working fine, returns string with data

            //let json = try? JSONSerialization.jsonObject( with: data, options: .mutableContainers)
            //print(json) //also working fine, returns json

            do{
                let stations = try JSONDecoder().decode([Station].self, from: data)
                print(stations) // returns nil
            } catch let jsonErr {
                print("Error: ", jsonErr)
                //Error:  typeMismatch(Swift.Double, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "gegrLat", intValue: nil)], debugDescription: "Expected to decode Double but found a string/data instead.", underlyingError: nil))
            }
        }.resume()
    }
}

The API response is array of objects, its look like: response example So i want to display list of this object in my application.

I would be really gratefull for any help

2
  • 1
    The error is telling you that gegrLat is a String in the JSON, not a Double. Commented May 15, 2020 at 19:05
  • There is a very simple JSON rule: Everything in double quotes is string, even "12.4" and "false". Commented May 15, 2020 at 19:23

1 Answer 1

1

Change your "Station" structure so gegrLon and gegrLat are Strings:

struct Station: Codable {
    var id: Int
    var stationName: String
    var gegrLat: String
    var gegrLon: String
    var city: City
    var addressStreet: String?
}

i.e your error is saying that is Expected to decode Double but found a string/data instead.

Sign up to request clarification or add additional context in comments.

7 Comments

Im so dumb, i didn't see it before. Now it works, thank you <3
Glad I could help. (If this was the right answer, you should let future users know by clicking the check mark next to it.)
It's better to instead implement init(from decoder: Decoder), and use it to parse those strings into the proper datatype, like a CLLocation or CLLocationCoordinate2D. Otherwise, your inter code will be litered with repeated parsing, probably force unwraps, and it would be a mess
@Alexander-ReinstateMonica I think for this example using a String makes sense.
@RickySanchez It most certainly doesn't. I can basically guarantee you that one of the next steps following parsing data like this is asking "how do I find the km distance between two pairs of strings that represent lat and long?", and if you don't have CLLocations, well... good luck with that
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.