需要从 open api 获取国家名称
Posted
技术标签:
【中文标题】需要从 open api 获取国家名称【英文标题】:need to get the country name from open api 【发布时间】:2019-01-10 12:50:16 【问题描述】:需要从下面的 api 调用中获取国家名称:
https://restcountries.eu/rest/v1/all
我的代码:
var arrRes = []
func getCountry()
let Url: String = "https://restcountries.eu/rest/v1/all"
Alamofire.request(Url).responseJSON (responseData) -> Void in
do
if let datas = responseData.result.value
let data = (datas as AnyObject).data(using: .utf8)!
let parseData = try JSONSerialization.jsonObject(with: data, options: [])
for country in parseData
if let name = country["name"] as? String
print(name)
catch let error as NSError
print(error)
这里出现错误:'Any' is not convertible to 'AnyObject'
在下面的行 let data = (datas as AnyObject).data(using: .utf8)!
..
我只需要获取名称并附加到我的数组。还有其他想法或解决方案来实现吗?
【问题讨论】:
How to access a Particular Value from a struct的可能重复 【参考方案1】:用这个替换do catch
语句块。
do
if let countries = responseData.result.value as? [[String: Any]]
for country in countries
if let name = country["name"] as? String
print(name)
catch let error as NSError
print(error)
【讨论】:
Cannot invoke 'jsonObject' with an argument list of type '(with: Any, options: [Any])'
on `let parseData = try JSONSerialization.jsonObject(with: datas, options: [])。我也试过了。。那个时候也是同样的错误
您不需要let error as NSError
部分。只需 catch print(error)
。
感谢@rmaddy 的提示。【参考方案2】:
试试这个,它对我来说很好用。
let urlStr = "https://restcountries.eu/rest/v1/all"
let setFinalURl = urlStr.addingPercentEncoding (withAllowedCharacters: .urlQueryAllowed)!
var request = URLRequest(url: URL(string: setFinalURl)!)
request.httpMethod = HTTPMethod.get.rawValue
Alamofire.request(request).responseJSON
(responseObject) -> Void in
if responseObject.result.isSuccess
print(responseObject.result.value!)
if "\(String(describing: responseObject.response!.statusCode))" == "200"
let result = responseObject.result.value! as AnyObject
let countryNamesArr = result.value(forKey: "name") as! NSArray
print(countryNamesArr)
else
// handle error
if responseObject.result.isFailure
let error : Error = responseObject.result.error!
print(error.localizedDescription)
【讨论】:
【参考方案3】:你可以试试
struct Root: Codable
let name: String
func getCountry()
let urlStr = "https://restcountries.eu/rest/v1/all"
Alamofire.request(urlStr).responseData (data) in
do
guard let data = data.data else return
let res = try JSONDecoder().decode([Root].self,from:data)
print(res)
catch
print(error)
【讨论】:
再次无法将“__NSArrayI”(0x1fa903a70)类型的值转换为“NSData”(0x1fa901dd8) @david 如果您需要 Codable 的数据,则无需做出 responseJson 做 reponseData【参考方案4】:删除这一行
let data = (datas as AnyObject).data(using: .utf8)!
并且在可选绑定中只需分配data
,因为value
是Data?
类型,从可选绑定中你会得到Data
if let data = responseData.result.value
然后不要忘记将您的 json 转换为数组 [String:Any]
...jsonObject(with: data, options: []) as? [[String:Any]]
...那么不要忘记解开这个数组,否则你将无法在每个循环中遍历它
还要注意,既然有Codable
,你应该使用它而不是JSONSerialization
。然后您可以使用 JSONDecoder
将您的 json 解码为您自己的符合协议 Decodable
的模型。
【讨论】:
有效答案。我建议尽量避免使用as!
,为了安全起见,您可以使用as?
;)【参考方案5】:
作为一种简单的方法,您可以像这样实现getCountry()
:
func getCountry()
let url: String = "https://restcountries.eu/rest/v1/all"
Alamofire.request(url).responseJSON response in
if let resultValue = response.result.value, let countryObjects = resultValue as? [[String: Any]]
let countryNames = countryObjects.compactMap $0["name"] as? String
print(countryNames)
此时,不需要使用JSONSerialization
来获取国名;根据 API 响应,responseData.result.value
是一个国家(字典)数组,每个字典都有一个“名称”值,您应该将响应 映射 到一个字符串数组。 countryNames
应该包含您要查找的内容。
使用compactMap
的好处是避免使用任何nil
名称,因此countryNames
应该是[String]
而不是[String?]
。
但是,如果您认为需要将整个响应对象转换为自定义对象(而不是字典),我强烈建议您遵循使用 Decodable
的方法。
【讨论】:
【参考方案6】:我的代码,对我来说效果很好。
斯威夫特 5
public func getCountry(completion: @escaping ([String]) -> ())
let url: String = "https://restcountries.eu/rest/v1/all"
AF.request(url).responseJSON (responseData) -> Void in
do
guard let data = responseData.data else return
let res = try JSONDecoder().decode([CountryName].self,from:data)
completion(self.getCountryName(countryName: res))
catch
print(error)
struct CountryName: Codable
let name: String
private func getCountryName(countryName:[CountryName]) -> [String]
var country:[String] = []
for index in 0...countryName.count - 1
country.append(countryName[index].name)
return country
【讨论】:
以上是关于需要从 open api 获取国家名称的主要内容,如果未能解决你的问题,请参考以下文章