How to create a function to show reviews in a view of my application (Swift-JSON)

I'm following https://developers.google.com/places/web-service/details this doc to add all the information about a place, and for example to add "geometry"

 "geometry" : {
         "location" : {
            "lat" : -33.866651,
            "lng" : 151.195827
         },

i created this function in my class that work well

private let geometryKey = "geometry"
private let locationKey = "location"
private let latitudeKey = "lat"
private let longitudeKey = "lng"

class EClass: NSObject  {

 var location: CLLocationCoordinate2D?

init(placeInfo:[String: Any]) {

        placeId = placeInfo["place_id"] as! String


        // coordinates
        if let g = placeInfo[geometryKey] as? [String:Any] {
            if let l = g[locationKey] as? [String:Double] {
                if let lat = l[latitudeKey], let lng = l[longitudeKey] {
                    location = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
                }
            }
        }
      }  

but but i'm having difficulty adding "reviews"

"reviews" : [
         {
            "author_name" : "Robert Ardill",
            "author_url" : "https://www.google.com/maps/contrib/106422854611155436041/reviews",
            "language" : "en",
            "profile_photo_url" : "https://lh3.googleusercontent.com/-T47KxWuAoJU/AAAAAAAAAAI/AAAAAAAAAZo/BDmyI12BZAs/s128-c0x00000000-cc-rp-mo-ba1/photo.jpg",
            "rating" : 5,
            "relative_time_description" : "a month ago",
            "text" : "Awesome offices. Great facilities, location and views. Staff are great hosts",
            "time" : 1491144016
         }
      ],

i tried to follow the same concept of the function i created for geometry like this

if let t = place.details?["reviews"] as? [String:Any] {
                   if let n = t["author_name"], let m = t["text"] {
                       Mylabel.text = "\(t)"
                   }

but is not working, i also tried to add a breakpoint and only the first line enters. What can i do? How can i create a build to show the review with a label or anything i need?

3 answers

  • answered 2018-01-19 11:07 Umair Aamir

    In your code t is not a Dictionary it is an Array instead. So try doing something like this. Rest of that you can change as per your logic.

    if let t = place.details?["reviews"] as? [String:Any] {
        for dic in t {
            if let n = dic["author_name"], let m = dic["text"] {
                Mylabel.text = "\(t)"
            } 
        }
    }
    

  • answered 2018-01-19 11:07 pkesaj

    Yeah, but You can also try to make it like that:

    struct reviews: Codable{
        var reviews: [review]?
    }
    struct review: Codable{
        var author_name: String?
        var author_url: String?
        var language: String?
        var profile_photo_url: String?
        var rating: Int?
        var relative_time_description: String?
        var text: String?
        var time: Int?
    }
    

    And then:

    if let dict = place.details?["reviews"] as? [String: Any], 
       let dataToDecode = dict.data(using: .utf8){
        do{
            let decodedReviews = try JSONDecoder().decode(reviews.self, from: dataToDecode)
    
         // here you have decoded reviews in array
        }catch let err{
            print(err)
        }
    }
    

  • answered 2018-01-19 11:07 Lorenzo B

    Take advantage of Codable in Swift 4. You can simply convert your JSON into a specific struct. e.g. Based on your JSON:

    let json = """
        {
            "reviews" : [
                {
                    "author_name" : "Robert Ardill",
                    "author_url" : "https://www.google.com/maps/contrib/106422854611155436041/reviews",
                    "language" : "en",
                    "profile_photo_url" : "https://lh3.googleusercontent.com/-T47KxWuAoJU/AAAAAAAAAAI/AAAAAAAAAZo/BDmyI12BZAs/s128-c0x00000000-cc-rp-mo-ba1/photo.jpg",
                    "rating" : 5,
                    "relative_time_description" : "a month ago",
                    "text" : "Awesome offices. Great facilities, location and views. Staff are great hosts",
                    "time" : 1491144016
                }
            ]
        }
        """
    

    You can convert it into a Response struct using the following code:

    struct Response: Codable {
    
        struct Review: Codable, CustomStringConvertible {
            let text: String
            let authorName: String
    
            var description: String {
                return "Review text: \(text) authorName: \(authorName)"
            }
    
            enum CodingKeys: String, CodingKey {
                case text
                case authorName = "author_name"
            }
        }
    
        let reviews: [Review]
    }
    
    do {
        if let data = json.data(using: .utf8) {
            let decoder = JSONDecoder()
            let decoded = try decoder.decode(Response.self, from: data)
            print(decoded.reviews)
        } else {
            print("data is not available")
        }
    } catch (let e) {
        print(e)
    }