1

I am trying to parse out the longitude and latitude of the London eye. My code is as follows

Here is my class:

struct Location: Decodable{
    let location: String
    let lat: Double
    let long: Double

}

Here is my Function

func getData(){
        let url = "URL FOR THE JSON"
        let urlOBJ = URL(string: url)

        URLSession.shared.dataTask(with: urlOBJ!){(data,response,errror) in

            do{
                let locations = try JSONDecoder().decode([Location].self, from: data!)

                for x in locations{
                    print(x.lat)
                }
            }

            catch{
                print("We got an error")
            }

    }.resume()

Here is my JSON response:

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "918",
               "short_name" : "918",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "12th Street",
               "short_name" : "12th St",
               "types" : [ "route" ]
            },
            {
               "long_name" : "New Westminster",
               "short_name" : "New Westminster",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Greater Vancouver",
               "short_name" : "Greater Vancouver",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "British Columbia",
               "short_name" : "BC",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Canada",
               "short_name" : "CA",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "V3M 6B1",
               "short_name" : "V3M 6B1",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "918 12th St, New Westminster, BC V3M 6B1, Canada",
         "geometry" : {
            "location" : {
               "lat" : 49.2122785,
               "lng" : -122.9368196
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 49.21362748029149,
                  "lng" : -122.9354706197085
               },
               "southwest" : {
                  "lat" : 49.21092951970849,
                  "lng" : -122.9381685802915
               }
            }
         },
         "place_id" : "ChIJt0rd0NB3hlQRWKnWCK79k1s",
         "plus_code" : {
            "compound_code" : "6367+W7 New Westminster, British Columbia, Canada",
            "global_code" : "84XV6367+W7"
         },
         "types" : [ "doctor", "establishment", "health", "point_of_interest" ]
      }
   ],
   "status" : "OK"
}

I want to extract the location from the geometry section of the response but think that I have mis understood how to get there. Any help is welcome as I am new to this.

When I run this I am redirected to my error message so I think it is just not finding the longitude or latitude.

Please ask if you have any questions regarding my code.

3
  • 2
    Never, never, never print a meaningless literal string like "We got an error" in a catch block when catching a Codable error. Don't do that. Print the error: print(error). Codable errors are extremely descriptive. They tell you exactly what's wrong. Commented Nov 28, 2018 at 17:58
  • 1
    @vadian this is the error I got : "typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))" Commented Nov 28, 2018 at 18:02
  • Please read the JSON: The root object is a dictionary ({}) which is not a Location. There is a key status and a key results. The value for key results is an array of another dictionary. This dictionary contains the key geometry and this object contains the key location. Commented Nov 28, 2018 at 18:04

2 Answers 2

1

So let's start from the raw response. You have a root - results and then you have geometry node with location subnode.

1. We will use the Codable protocol to make parsing easier:

struct RawResponseRoot: Codable {
    let results: [RawResponse]
}

struct RawResponse: Codable {

    struct Geometry: Codable {
        let location: Location
    }

    struct Location: Codable {
        private enum CodingKeys: String, CodingKey {
            case latitude = "lat", longitude = "lng"
        }
        let latitude: Double
        let longitude: Double
    }

    let name: String
    let geometry: Geometry
}

2. Create a Venue struct to hold your location and name of the location:

struct Venue: Codable {
    let name: String
    let latitude: Double
    let longitude: Double

    init(from rawResponse: RawResponse) throws {
        self.name = rawResponse.name
        self.latitude = rawResponse.geometry.location.latitude
        self.longitude = rawResponse.geometry.location.longitude
    }
}

3. Then in your getData function do extract the results:

func getData(){
    let url = "URL FOR THE JSON"
    let urlOBJ = URL(string: url)

    URLSession.shared.dataTask(with: urlOBJ!){(data,response,error) in
          guard let data = data, let root = try? JSONDecoder().decode(RawVenueResponseRoot.self, from: data) else {
              print("Error retrieving data:", error)
              return
          }

        let locations = root.results.compactMap({ try? Venue(from: $0) })

}.resume()
Sign up to request clarification or add additional context in comments.

Comments

0

I think you should go through some basic codable tutorials. You are making many mistakes. For instance, your location struct is not the same as that of JSON. In the JSON, the longitude key is "lng" but in your struct, it is "long".

Go through this

https://benscheirman.com/2017/06/swift-json/

It covers the basics as well as many different use cases.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.