Search code examples
jsonswifthttprequestgoogle-elevation-api

JSON response decoding to nil in swift


struct Jresponse: Decodable{
            //var results: [Any]
            var resolution: Int?
            var elevation:  Int?
            var location: Int?
            var lat: Int?
            var lng: Int?
        }
        guard let url = URL(string: "https://maps.googleapis.com/maps/api/elevation/json?&locations=\(finalStringConvertedCoordinates)&key=\(apiKey)") else {
                    print("Error: cannot create URL")
                    return
                }
                // Create the url request
                var request = URLRequest(url: url)
                request.httpMethod = "GET"
                URLSession.shared.dataTask(with: request) { data, response, error in
                    guard error == nil else {
                        print("Error: error calling GET")
                        print(error!)
                        return
                    }
                    guard let data = data else {
                        print("Error: Did not receive data")
                        return
                    }
                    guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else {
                        print("Error: HTTP request failed")
                        return
                    }
                    do {
                        guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                            print("Error: Cannot convert data to JSON object")
                            return
                        }
                        guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
                            print("Error: Cannot convert JSON object to Pretty JSON data")
                            return
                        }
                        guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8)
                        else {
                            print("Error: Could print JSON in String")
                            return
                        }
                        //print(prettyPrintedJson)
                        jsonResponse = prettyPrintedJson
                    } catch {
                        print("Error: Trying to convert JSON data to string")
                        return
                    }
                    let decoder = JSONDecoder()
                    let jrData = jsonResponse.data(using: .utf8)
                    let jsonResponseProcessed = try! decoder.decode(Jresponse.self, from: jrData! )
                    print(jsonResponseProcessed)
                }.resume()
        
            }

the code above contains both the request and decoding of the response, I am inexperienced with JSON which may be apparent.

The issue I have is the results being returned when printing are all nil.

previously I was not using decode and instead was trying to process the data into an array where individual values could be retrieved for comparison.

The array method was producing unmanageable data as the elements where not separated in a manageable order.

like this[The nil response][1]

OUTPUT with the inclusion of print("---> data: (String(data: data, encoding: .utf8))") looks like this.

[The output can be seen here][2]

---> data: Optional("{\n "results" : [\n {\n "elevation" : 11.59268283843994,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4059982299805\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.68190288543701,\n "location" : {\n "lat" : 37.78538513183594,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.86490249633789,\n "location" : {\n "lat" : 37.78548812866211,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.53255939483643,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4061584472656\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.46291351318359,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4063262939453\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.69645023345947,\n "location" : {\n "lat" : 37.78558731079102,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.79109859466553,\n "location" : {\n "lat" : 37.78569030761719,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.35733222961426,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4064865112305\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.57364559173584,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4066467285156\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.7429027557373,\n "location" : {\n "lat" : 37.78578948974609,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.02133083343506,\n "location" : {\n "lat" : 37.78589248657227,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.66207313537598,\n "location" : {\n "lat" : 37.78533554077148,\n "lng" : -122.4068145751953\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 11.85497093200684,\n "location" : {\n "lat" : 37.78536987304688,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.22011947631836,\n "location" : {\n "lat" : 37.78599548339844,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.59670543670654,\n "location" : {\n "lat" : 37.78609466552734,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.19275951385498,\n "location" : {\n "lat" : 37.78546905517578,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.13292598724365,\n "location" : {\n "lat" : 37.78557205200195,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.98763847351074,\n "location" : {\n "lat" : 37.78619766235352,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 13.3654317855835,\n "location" : {\n "lat" : 37.78629684448242,\n "lng" : -122.4059143066406\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.14237785339355,\n "location" : {\n "lat" : 37.78567504882812,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.26948738098145,\n "location" : {\n "lat" : 37.78577423095703,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 13.74397277832031,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4060211181641\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 14.1032075881958,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4061889648438\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.31325626373291,\n "location" : {\n "lat" : 37.7858772277832,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.36202812194824,\n "location" : {\n "lat" : 37.78598022460938,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 14.12999248504639,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4063491821289\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 14.4321174621582,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4065093994141\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 12.53042221069336,\n "location" : {\n "lat" : 37.78607940673828,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 13.14097881317139,\n "location" : {\n "lat" : 37.78618240356445,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 14.39413261413574,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4066696166992\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 14.40865802764893,\n "location" : {\n "lat" : 37.78633499145508,\n "lng" : -122.4068374633789\n },\n "resolution" : 0.5964969992637634\n },\n {\n "elevation" : 13.98401737213135,\n "location" : {\n "lat" : 37.78628158569336,\n "lng" : -122.4069137573242\n },\n "resolution" : 0.5964969992637634\n }\n ],\n "status" : "OK"\n}\n") Jresponse(resolution: nil, elevation: nil, location: nil, lat: nil, lng: nil) [1]: https://i.sstatic.net/uaRZZ.png [2]: https://i.sstatic.net/MWJZX.png


Solution

  • Decoding failed

    The most likely reason that you cannot get any data is that your data model (here defined as a struct Jresponse) does not fit the actual JSON format sent back by the backend.

    I've quickly check google map api doc for elevation and it seems like you should receive a json object with an array of ElevationResult at the top level. Then each result would contain the resolution, the elevation and location.

    Please refer to https://developers.google.com/maps/documentation/elevation/overview#ElevationResult

    Correct Data Model

    
    struct ElevationResponse: Decodable {
        let results: [ElevationResult]
    }
    
    struct ElevationResult: Decodable {
         let elevation: Double
         let location: LatLngLiteral
         let resolution: Double?
    }
    
    struct LatLngLiteral: Decodable {
         let lat: Double
         let lng: Double
    }
    
    

    Change model in your decoding

    let jsonResponseProcessed = try! decoder.decode(ElevationResponse.self, from: data)
    

    Side remarks

    1. The way you decode the data could be modernized and cleaner
    2. Pay attention to not use force unwrap and force try
    3. When posting your question, be careful to the code indentation, first select your code in Xcode and do a ctrl + i so that it improves its readability. Only then copy past it into your Stackoverflow question.