从 JSON 文件问题中读取国家名称

Posted

技术标签:

【中文标题】从 JSON 文件问题中读取国家名称【英文标题】:Reading countries names from JSON file problem 【发布时间】:2018-10-19 16:20:13 【问题描述】:

我正在尝试使用 swift 从 json 文件中加载和解析国家名称,但我不能

这是我尝试读取的文件格式:Countries JSON File

我执行此任务的代码:

func getJsonFromUrl()
    let url = NSURL(string: COUNTRIES_URL)
    URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: (data, response, error) -> Void in
        if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary 
            if let countries_array = jsonObj!.value(forKey: "name") as? NSArray 
                for country in countries_array 
                    if let countryDict = country as? NSDictionary 
                        if let name = countryDict.value(forKey: "name") 
                            self.countries_names.append((name as? String)!)
                        
                    
                
            
            OperationQueue.main.addOperation (
                self.showNames()
            )
        
    ).resume()

但是当我运行它时,它在这一行给我一个错误: if let countries_array = jsonObj!.value(forKey: "name") as? NSArray 因为意外的 nil。

【问题讨论】:

你的if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary 应该是as? Array<[String: Any]>,因为最上面的对象实际上是一个数组 【参考方案1】:

JSON 以方括号 ([) 开头,因此根对象是一个数组

不要在 Swift 中使用 NSURLNSArrayNSDictionaryvalue(forKey

并处理可能的错误。

func getJsonFromUrl() 
    let url = URL(string: COUNTRIES_URL)!
    URLSession.shared.dataTask(with: url!, completionHandler: (data, response, error) -> Void in
        if let error = error  print(error); return 
        do 
            if let countriesArray = try JSONSerialization.jsonObject(with: data!) as? [[String:String]] 
                for country in countriesArray 
                    self.countries_names.append(country["name"]!)
                
            
         catch  print(error) 
        OperationQueue.main.addOperation (
            self.showNames()
        )
    ).resume()

或者使用Decodable 更方便

struct Country : Decodable 
    let name : String


func getJsonFromUrl() 
    let url = URL(string: COUNTRIES_URL)!
    URLSession.shared.dataTask(with: url!, completionHandler: (data, response, error) -> Void in
        if let error = error  print(error); return 
        do 
            let countries = try JSONDecoder().decode([Country].self, from: data!)
            self.countries_names = countries.map$0.name
         catch  print(error) 
        OperationQueue.main.addOperation (
            self.showNames()
        )
    ).resume()

【讨论】:

也尽量不要使用强制展开 @AdityaSrivastava 在这种情况下,一切都非常安全。 URL 字符串是一个常量,data 如果errornil 并且JSON 一致,则data 有效。您甚至可以强制将向下转换为 [[String:String]]【参考方案2】:

你需要的是数组而不是字典

if let dat = data 
   if let jsonObj = try? JSONSerialization.jsonObject(with: dat, options:[]) as? [[String:String]]
   jsonObj.forEach  print($0["name"])     

或使用Codable

let res = try? JSONDecoder().decode([[String:String]].self,from:data)

或与模型

struct Root: Codable 
  let name : String


let res = try? JSONDecoder().decode([Root].self,from:data)

【讨论】:

以上是关于从 JSON 文件问题中读取国家名称的主要内容,如果未能解决你的问题,请参考以下文章

如何从文本文件中读取选定的列

TypeError:无法读取未定义的属性(读取“国家”)

我如何在 Xamarin 中读取两个同名的 json 数据

PySpark 从目录中读取多个 txt 文件为 json 格式

如何从目录中读取文件并作为 JSON 发送给客户端?

如何在 Ionic 中读取我的 json 数组的属性“名称”