远程 JSON 还是本地 JSON?
接下来的任务是显示目的地机场附近的 10 家宾馆。这需要远程获取数据。
应该本地存放数据,还是在处理每个请求时都远程地获取数据?对于这个问题,没有标准的答案。对于机场数据集,我觉得完全可以本地存放。这样的数据很容易得到,而且体积不大,容易存放。(美国只有 901 个机场,很多主要的机场基本上是保持不变的,这份列表不会那么快就过时)。
如果机场数据集不稳定,并且太大不便本地存储,或者不能单独下载,那么我会更倾向于远程地请求它。您在 “Grails 服务和 Google 地图” 中用过的 geonames.org geocoding 服务提供 JSON 输出和 XML(请参阅 参考资料)。在 Web 浏览器中输入 http://ws.geonames.org/search?name_equals=den&fcode=airp&style=full&type=json。应该可以看到清单 13 所示的 JSON 结果:
清单 13. 从 GeoNames 返回的 JSON 结果
"geonames":[
{"alternateNames":[
{"name":"DEN","lang":"iata"},
{"name":"KDEN","lang":"icao"}],
"adminCode2":"031",
"countryName":"United States",
"adminCode1":"CO",
"fclName":"spot, building, farm",
"elevation":1655,
"countryCode":"US",
"lng":-104.6674674,
"adminName2":"Denver County",
"adminName3":"",
"fcodeName":"airport",
"adminName4":"",
"timezone":{
"dstOffset":-6,
"gmtOffset":-7,
"timeZoneId":"America/Denver"},
"fcl":"S",
"name":"Denver International Airport",
"fcode":"AIRP",
"geonameId":5419401,
"lat":39.8583188,
"population":0,
"adminName1":"Colorado"}]
}
可以看到,GeoNames 服务比您在 “Grails 与遗留数据库” 中导入的 USGS 提供更多关于机场的信息。如果出现新的用户需求,例如需要知道机场的时区或海拔高度,GeoNames 还可以提供另一种令人感兴趣的结果。它还包括像 London Heathrow(LHR)和 Frankfort(FRA)这样的国际机场。您可以将 AirportMapping.iata() 转换为使用 GeoNames,这是一个课外练习。
同时,为了显示目的地机场附近的宾馆,惟一有效的选项是利用一个远程 Web 服务。由于有数千家宾馆,而且??馆列表是不断变化的,所以必须让其他人负责管理这份列表。
Yahoo! 提供了一个本地搜索服务,通过该服务可以搜索一个街道地址、邮政编码,甚至是一个经度/纬度点附近的企业(请参阅 参考资料)。如果您在 “RESTful Grails” 中已经注册并得到一个 developer 密匙,那么可以在这里重用它。毫不奇怪,您在那时使用的一般搜索 URI 的格式与现在要使用的本地搜索非常类似。上一次,您允许 Web 服务默认地返回 XML。但是,通过添加一个 name=value 对(output=json),就可以得到 JSON。
在浏览器中输入以下内容(不要换行),看看 Denver International Airport 附近的宾馆的 JSON 列表:
YahooDemo&query=hotel&latitude=39.858409881591797&longitude=
-104.666999816894531&sort=distance
清单 14 显示了 JSON 结果(删节):
清单 14. Yahoo! 返回的 JSON 结果
{"totalResultsAvailable":"803",
"totalResultsReturned":"10",
"firstResultPosition":"1",
"ResultSetMapUrl":"http:\/\/maps.yahoo.com\/broadband\/?tt=hotel&tp=1",
"Result":[
{"id":"42712564",
"Title":"Springhill Suites-Denver Arprt",
"Address":"18350 E 68th Ave",
"City":"Denver",
"State":"CO",
"Phone":"(303) 371-9400",
"Latitude":"39.82076",
"Longitude":"-104.673719",
"Distance":"2.63",
[SNIP]
现在,您有了一个可用的宾馆列表,接下来需要为其创建一个控制器方法,就像为 AirportMapping.iata() 创建该方法一样。