2017-01-09 88 views
1

我在Swift 3中構建iOS應用程序,並使用Google Places API獲取地點數據。我正在使用iOS API來獲取大部分我需要的數據。但我也需要獲得iOS API尚未提供的開放時間。iOS Swift - Google Place API(Web)以奇怪格式返回JSON

所以我必須查詢Web API來獲取該信息。事情的請求方面工作正常,但是,一旦我得到結果,我把它變成JSON與JSONSerialisation,然後在控制檯中打印輸出,這種JSON的格式很奇怪,我努力解析它。

當我把它粘貼到一個JSON閱讀器時,它說它是無效的。

這裏是一個看起來很奇怪,我與這些 「(」 和 「=」 的JSON:

["html_attributions": <__NSArray0 0x17001ccf0>(

) 
, "result": { 
    "address_components" =  (
       { 
      "long_name" = 611; 
      "short_name" = 611; 
      types =    (
       "street_number" 
      ); 
     }, 
       { 
      "long_name" = "Post Street"; 
      "short_name" = "Post St"; 
      types =    (
       route 
      ); 
     }, 
       { 
      "long_name" = "Lower Nob Hill"; 
      "short_name" = "Lower Nob Hill"; 
      types =    (
       neighborhood, 
       political 
      ); 
     }, 
       { 
      "long_name" = "San Francisco"; 
      "short_name" = SF; 
      types =    (
       locality, 
       political 
      ); 
     }, 
       { 
      "long_name" = "San Francisco County"; 
      "short_name" = "San Francisco County"; 
      types =    (
       "administrative_area_level_2", 
       political 
      ); 
     }, 
       { 
      "long_name" = California; 
      "short_name" = CA; 
      types =    (
       "administrative_area_level_1", 
       political 
      ); 
     }, 
       { 
      "long_name" = "United States"; 
      "short_name" = US; 
      types =    (
       country, 
       political 
      ); 
     }, 
       { 
      "long_name" = 94109; 
      "short_name" = 94109; 
      types =    (
       "postal_code" 
      ); 
     } 
    ); 
    "adr_address" = "<span class=\"street-address\">611 Post St</span>, <span class=\"locality\">San Francisco</span>, <span class=\"region\">CA</span> <span class=\"postal-code\">94109</span>, <span class=\"country-name\">USA</span>"; 
    "formatted_address" = "611 Post St, San Francisco, CA 94109, USA"; 
    "formatted_phone_number" = "(415) 817-1391"; 
    geometry =  { 
     location =   { 
      lat = "37.7877411"; 
      lng = "-122.4120067"; 
     }; 
     viewport =   { 
      northeast =    { 
       lat = "37.78791149999999"; 
       lng = "-122.4119977"; 
      }; 
      southwest =    { 
       lat = "37.7876843"; 
       lng = "-122.4120337"; 
      }; 
     }; 
    }; 
    icon = "https://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png"; 
    id = 6a6d8b640d5260886eac5ce1b3aa73b3b0d0bb1c; 
    "international_phone_number" = "+1 415-817-1391"; 
    name = "Joy's Place"; 
    "opening_hours" =  { 
     "open_now" = 1; 
     periods =   (
         { 
       close =     { 
        day = 1; 
        time = 0000; 
       }; 
       open =     { 
        day = 0; 
        time = 0800; 
       }; 
      }, 
         { 
       close =     { 
        day = 2; 
        time = 0000; 
       }; 
       open =     { 
        day = 1; 
        time = 0700; 
       }; 
      }, 
         { 
       close =     { 
        day = 3; 
        time = 0000; 
       }; 
       open =     { 
        day = 2; 
        time = 0700; 
       }; 
      }, 
         { 
       close =     { 
        day = 4; 
        time = 0000; 
       }; 
       open =     { 
        day = 3; 
        time = 0700; 
       }; 
      }, 
         { 
       close =     { 
        day = 5; 
        time = 0000; 
       }; 
       open =     { 
        day = 4; 
        time = 0700; 
       }; 
      }, 
         { 
       close =     { 
        day = 6; 
        time = 0000; 
       }; 
       open =     { 
        day = 5; 
        time = 0700; 
       }; 
      }, 
         { 
       close =     { 
        day = 0; 
        time = 0000; 
       }; 
       open =     { 
        day = 6; 
        time = 0800; 
       }; 
      } 
     ); 
     "weekday_text" =   (
      "Monday: 7:00 am \U2013 12:00 am", 
      "Tuesday: 7:00 am \U2013 12:00 am", 
      "Wednesday: 7:00 am \U2013 12:00 am", 
      "Thursday: 7:00 am \U2013 12:00 am", 
      "Friday: 7:00 am \U2013 12:00 am", 
      "Saturday: 8:00 am \U2013 12:00 am", 
      "Sunday: 8:00 am \U2013 12:00 am" 
     ); 
    }; 
    photos =  (
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/109383364523945736298/photos\">Kathleen S</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAFE8a_M5quVcX6frenilHEFVXTycrrhj5R3MoS5sd_vKG1Gj46aJVAvVl_a4HVcPS4G5Z2JS00Pugdegn4is9KSfwIw6IoMNBL1zo3hK2dQjfArUezH9wfSYpNJCNzi4bUO6EesC4bT74B1-hzM6Us4gzKpLLAfImaF3VTeRX-SGEhCLAqUUWZsgueYvTkx8mEi8GhRCDxXbJR-ddaQFwJizvZIKa4EYKA"; 
      width = 4032; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/109935156740971751576/photos\">Jake Lim</a>" 
      ); 
      "photo_reference" = "CoQBdwAAANPkBrIvYxn3UrYliLvLgk3Z4tOmS_twOv9nbMSTFmAR00Mff8XCMWQRUeigOYw1dSheyerBgimteHAHdRMzTCAWkJ7V2yB0eBS5HBewcw2yKmGHrCuCxZDdBlovGzJrwhfo5cAUB0lFDIfAXfDGnNWifD8OmLdfEzsZt97peyIrEhC84xqRQnlK32XjZkXE5huQGhQiPI0EjQ284RkMqiYxwnoHVpXOMg"; 
      width = 4032; 
     }, 
       { 
      height = 2048; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/111937150500795140908/photos\">Hope Lynch</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAFMi1hIXlNKawhA7RPl9Oah4OS6ZZyNnBRpgkHtT5gCC0brwkl55azVyulgOLsYeBkz7lpDgrpW4_9A2vg6Dtcg1bf3vVYVb1PbvADXJAV8yNwmRu9xvfSaPlgl3ty7WKW2tl8Znv8pnTMtOxfYBiTqLuFpLiEdt03pmqQMtrTKSEhADBNOSal9jDonQAMac7ghIGhTkHYMlxquEKYBuKNlbJxYY2sMmxQ"; 
      width = 1536; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/100358998671099081635/photos\">\Uc784\Uc77c\Uc8fc</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAClp7S-w50auLq1Rtet0Glz5UjwWmSFGWKsceURE2ydHve0hFYZqf-OewYNm7xqRBA_Vdtl-nNSIgHawN5JCfyXW48fMRFi7L1mYiycxPjpZSwcH8VlQUisS1dEURkbSaY7lBH1niz197x0hhK0eTIdaPjsXboXcij7xQm6bsYSYEhDt416My2DDwuNUg7MWDrzDGhTIxwfK1eBLCjzto2X_10Ed9pvsyQ"; 
      width = 4032; 
     }, 
       { 
      height = 5312; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/113957702965980710581/photos\">Tim Lee</a>" 
      ); 
      "photo_reference" = "CoQBdwAAANNU12JQOxIa6Y4MBHzNedo42kZmStvSbw_JF-lhdCOtj7QoiuwfWvj1MjECq29AO7CM3QFeJiQQn3cV3GWilWHoI0EDXBodlGRe3MAG6tNhBnKBYB_jNuM_muu2o1ngWmsOXP6cmcuZmxK1z5w5cDX_aUrpli4vkKRkNuqIdbc_EhACCVmjsS6GxgLanF9s9KrVGhSEL_DpaNArYwocJzkX688WFLsEUQ"; 
      width = 2988; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/109383364523945736298/photos\">Kathleen S</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAK8OjkKwRH84A_OKMhCXVemX8vxLS8nCp7c30JOvt7SiqGL5_XQCKz03ZiH-Tq2sshn_UBKttz3oyDJIhfAT2VTuDZgnbAPCSlNQUoP80yeATWPJJFcjJ4XxsKcQHF6Y5IDFzszEIAJYhMBQJ9I6RKMaBGMlRftIZeAEkFhN5AEtEhAozH6UEf-m0XthHPES1ldPGhTB3-JgPzRJ8aDX-B5_SyW2vs4E8Q"; 
      width = 4032; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/114832380918896847951/photos\">Deby Lepage</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAJyut1B1yUQD6mq1FD8gQVNKo16sS6-xbnGeSs8jDtb3C5oF_oUcoUGpLTnQpHqxHfsFh7oL7cBud_h-h0xc2fhNuIkMBFQEWeZhCrmoqph5U79sH98jtOKJgjxs6i0W3-cyDlyURIux8oBfB3QzNhLqeHapJ_WFAMai74Z5ufo1EhDlCT1tkYirOAlgg18i1MVEGhQ_StyBaN3neLaiKNN2s-cTFEPz1w"; 
      width = 4032; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/114832380918896847951/photos\">Deby Lepage</a>" 
      ); 
      "photo_reference" = "CoQBdwAAAJ-OEm5p7FZZFsPIUBBlB-v5uPhGz3K_j9qD4fIF7lUTFUW3I_-O9gy_MZCUkD5XlZJXa2F9kfZ4Ru-Eb989IYc6YQzc3i_N3ozUOyuPhL2FDUqqkl-pltfNJJBoSOlDp4M4Ay9yrKQP6BpUP8i9P9L0gDgv-ycKDIWNh-vUDmtwEhA6F3RmxZ_tsbE131S_RcYoGhTOQTkUt1Zm9b8qUD7yxiWTjemxxQ"; 
      width = 4032; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/109383364523945736298/photos\">Kathleen S</a>" 
      ); 
      "photo_reference" = "CoQBdwAAANkAGV7dv_jVNv_mGmJ9ilcPKJ9Vx24Fs1MEwy0Ce6B6hoGZ-8I0pbFVjS99TicGo3zGdi6eUbpEm76C5XplnnkuM4HGWLN1PkzHk98vVeY4hJRGY1o2qnoLaf6DnvPBmhpbrucCJK9WCNRH3-q1UZ6lzFwgxEwFAxbf-KSwJRqkEhD2Si7TWKZNQcb7bXy29QaVGhR7Yk3dOMasHvsoNwa9y-FMxzNV4w"; 
      width = 4032; 
     }, 
       { 
      height = 3024; 
      "html_attributions" =    (
       "<a href=\"https://maps.google.com/maps/contrib/114832380918896847951/photos\">Deby Lepage</a>" 
      ); 
      "photo_reference" = "CoQBdwAAABqKoM9Is_KWHUlzFyDIAOh41GwUaOqPC5EwWqB_uwDTRsB4XbOksl4qylHlSbTuXpRrUUaAETi-I0coY8KyLtS5E6NxcM4f93iMl6kgsb8apJRGziedKV99EUNcdeaTWmWJOuxirP_7wwiadwUiwbmfjZ05e2EkAtfmjCb8vHTYEhDsAfUeyhcyQu_riR-Vrd9JGhRwlTegpWWdYn9uVGVhs02SjIyXsQ"; 
      width = 4032; 
     } 
    ); 
    "place_id" = "ChIJheCrEY6AhYARxCkT8_KjDWE"; 
    rating = "4.4"; 
    reference = "CmRRAAAAeYm_xV5gsn_eVlrvpkEolaqaHFO0CWS5rWXJ5z5QWX8ReJKLPl6eDnvFM0PD2BNMkgfui9Z42_jmUxCIeTeZi3OEaod73XuU_rzLpRAdlOm8IcTaLX6YeYJeS4qFqZxLEhBUzZmWo-SU9WY4YG8WP8GOGhSwAPbhHWRuZh0X6wC1LMD3Los44A"; 
    reviews =  (
       { 
      aspects =    (
           { 
        rating = 2; 
        type = overall; 
       } 
      ); 
      "author_name" = "Lanxin Chu"; 
      "author_url" = "https://www.google.com/maps/contrib/117750042826931398790/reviews"; 
      language = en; 
      rating = 4; 
      "relative_time_description" = "5 months ago"; 
      text = "Red bean shaved ice was good and definitely did not skimp out on ingredients! Green tea latte was solid. Ambiance was pretty nice. There were a lot of people studying there; as noted by others this makes for somewhat limited seating sometimes so keep that in mind."; 
      time = 1470610849; 
     }, 
       { 
      aspects =    (
           { 
        rating = 3; 
        type = overall; 
       } 
      ); 
      "author_name" = "Esther Gibbs"; 
      "author_url" = "https://www.google.com/maps/contrib/110692487628239988503/reviews"; 
      language = en; 
      rating = 5; 
      "relative_time_description" = "a month ago"; 
      text = "Delicious food and drink- especially their sweet potato latte! Fairtrade and organic everything and a lovely working environment"; 
      time = 1479462640; 
     }, 
       { 
      aspects =    (
           { 
        rating = 2; 
        type = overall; 
       } 
      ); 
      "author_name" = "Johnny Wang"; 
      "author_url" = "https://www.google.com/maps/contrib/103379264202553362035/reviews"; 
      language = en; 
      "profile_photo_url" = "//lh6.googleusercontent.com/-EtpIyKVUteI/AAAAAAAAAAI/AAAAAAAAA4c/riPrz4_6j-s/photo.jpg"; 
      rating = 4; 
      "relative_time_description" = "7 months ago"; 
      text = "It's been called to my attention that I never reviewed this place, despite the number of times I've visited, which is... surprising. Honestly though, there's not too much to say: I've only ever come here for the patbingsoo, which is massively generous in portion size, and fantastically delicious in flavor, and definitely ideal for sharing. But hey, everything can be a personal serving if you try hard enough.\n\nAs for the place itself, it's a nice, chill little cafe that's been packed every single time I go, so seating can be a little hard to find at times. You'll usually find it occupied by folks busy working away on their laptops.\n\n***Accessibility Info***\n\nVenue - On the smaller side, as far as cafes/coffee shops go, with about 2/3 of the seating being accessible: those along the walls were bench seating, and there's lower coffee table seating towards the right as well, leaving only the middle aisle and outer seats along the sides accessible.\n\nBathroom - Didn't try them."; 
      time = 1465162538; 
     }, 
       { 
      aspects =    (
           { 
        rating = 2; 
        type = overall; 
       } 
      ); 
      "author_name" = "Victor Vu"; 
      "author_url" = "https://www.google.com/maps/contrib/108347888656400683025/reviews"; 
      language = en; 
      "profile_photo_url" = "//lh4.googleusercontent.com/-92ZhOOjfwfE/AAAAAAAAAAI/AAAAAAAAZqA/16j_bEwt6fk/photo.jpg"; 
      rating = 4; 
      "relative_time_description" = "7 months ago"; 
      text = "Great place to study... when it's quiet. There's enough light to clearly see your paperwork. Music is on the medium side and easy to phase out when you put on headphones, or focus really hard. It's really chill!\n\nFood and drinks are nice. It's a great place for coffee and deserts. Most people get waffles or ice cream here. Their matcha green tea is nice as well.\n\nThe only problem is that there is never enough seating during peak hours and it gets claustrophobic when it's crowded with people doing their homework.\n\nSeats are also cheap and hurt your butt.\n\nThis place usually attracts the Asian crowd."; 
      time = 1463551785; 
     }, 
       { 
      aspects =    (
           { 
        rating = 1; 
        type = overall; 
       } 
      ); 
      "author_name" = "Brian Melton"; 
      "author_url" = "https://www.google.com/maps/contrib/103909645378067844462/reviews"; 
      language = en; 
      "profile_photo_url" = "//lh4.googleusercontent.com/-enGmeXKqYC0/AAAAAAAAAAI/AAAAAAAA4eo/maQQGZ8Etdo/photo.jpg"; 
      rating = 3; 
      "relative_time_description" = "a month ago"; 
      text = "Expensive, small-sized coffees make this coffee shop feel like poor value-for-money. Limited food options but has great desserts: try the macaroons."; 
      time = 1480554027; 
     } 
    ); 
    scope = GOOGLE; 
    types =  (
     cafe, 
     restaurant, 
     food, 
     store, 
     "point_of_interest", 
     establishment 
    ); 
    url = "https://maps.google.com/?cid=6993426060231780804"; 
    "utc_offset" = "-480"; 
    vicinity = "611 Post Street, San Francisco"; 
    website = "http://www.joysplacecafe.com/"; 
}, "status": OK] 

這裏是我的代碼與虛擬查詢:

let url = URL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJheCrEY6AhYARxCkT8_KjDWE&key=[MYAPIKEY]") 

let urlRequest = URLRequest(url: url!) 


let task = URLSession.shared.dataTask(with: urlRequest) { 
    (data, response, error) in 

    guard error == nil else { 
     print(error!) 
     return 
    } 

    guard let responseData = data else { 
     print("Error: did not receive data") 
     return 
    } 

    do { 
     guard let placeData = try JSONSerialization.jsonObject(with: responseData, options: JSONSerialization.ReadingOptions.allowFragments) 
      as? [String: Any] else { 
       print("error trying to convert data to JSON") 
       return 
     } 

     print("The placeData is: \(placeData.description)") 

     guard let website = placeData["website"] as? String else { 
      print("Could not get the website from JSON") 
      return 
     } 
     print("The title is: \(website)") 
    } catch { 
     print("error trying to convert data to JSON") 
     return 
    } 
} 
task.resume() 

任何幫助瞭解正在發生的事情都將不勝感激。最終目標是讓開放時間成爲詞典,其中關鍵是一週的日子,值是開放時間。

在此先感謝

+0

謝謝埃裏克,看起來我確實感到困惑。將研究這一點。我是新來的;) –

回答

1

的問題是,reponseData是用鑰匙response字典包含要實際的字典。該JSON看起來像:

{ 
    "result": { 
     "website": "example.com" 
    } 
} 

所以正確的代碼是:

let url = URL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJheCrEY6AhYARxCkT8_KjDWE&key=[MYAPIKEY]") 

let urlRequest = URLRequest(url: url!) 


let task = URLSession.shared.dataTask(with: urlRequest) { 
    (data, response, error) in 

    guard error == nil else { 
     print(error!) 
     return 
    } 

    guard let responseData = data else { 
     print("Error: did not receive data") 
     return 
    } 

    do { 
     guard let placeData = try JSONSerialization.jsonObject(with: responseData, options: JSONSerialization.ReadingOptions.allowFragments) 
      as? [String: Any] else { 
       print("error trying to convert data to JSON") 
       return 
     } 

     print("The placeData is: \(placeData.description)") 

     guard let website = (placeData["result"] as? [String : Any])?["website"] as? String else { 
      print("Could not get the website from JSON") 
      return 
     } 
     print("The title is: \(website)") 
    } catch { 
     print("error trying to convert data to JSON") 
     return 
    } 
} 
task.resume() 

我只是改變:

guard let website = placeData["website"] as? String else {

到:

guard let website = (placeData["result"] as? [String : Any])?["website"] as? String else {

+0

謝謝Coder256!有點混亂,因爲這是我第一次這樣做。我已經嘗試了你的代碼示例,並且我得到了我想要的。 –