【问题标题】:Converting JSON to array in Swift 2在 Swift 2 中将 JSON 转换为数组
【发布时间】:2016-12-22 19:37:19
【问题描述】:

我需要为分组UITableView 构建Arrays,每个表格单元格中都有一个标题和详细信息行。我已经从服务器获得了我的 json 输出,将其置于正确的形状以迭代 UITableViewDataSource 方法。但是,将这些转换为UITableView 函数可以引用的可读数组的最简单方法是什么?

标题数组用于组标题,因此它只是一个一维数组。我可以重复这一点。标题和详细信息数组都是二维的。我不知道如何在 Swift 中做到这一点。

"headings":["Tuesday, August 16, 2016","Wednesday, August 17, 2016","Thursday, August 18, 2016","Friday, August 19, 2016","Saturday, August 20, 2016","Sunday, August 21, 2016","Monday, August 22, 2016","Tuesday, August 23, 2016","Wednesday, August 24, 2016","Thursday, August 25, 2016","Friday, August 26, 2016","Saturday, August 27, 2016","Sunday, August 28, 2016","Monday, August 29, 2016","Tuesday, August 30, 2016","Wednesday, August 31, 2016","Thursday, September 1, 2016","Friday, September 2, 2016","Saturday, September 3, 2016","Sunday, September 4, 2016","Monday, September 5, 2016","Tuesday, September 6, 2016","Wednesday, September 7, 2016","Thursday, September 8, 2016","Friday, September 9, 2016","Saturday, September 10, 2016","Sunday, September 11, 2016","Monday, September 12, 2016","Tuesday, September 13, 2016","Wednesday, September 14, 2016","Thursday, September 15, 2016","Friday, September 16, 2016"],

"titles":[["Joe Johnson"],["Joe Johnson"],["Sandy Primmell","Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Sandy Primmell","Joe Johnson"],["Joe Johnson","Joe Johnson"],["Sandy Primmell","Joe Johnson"],["Mark Greene","Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Sandy Primmell","Joe Johnson"],["Joe Johnson"],["Sandy Primmell","Joe Johnson"],["Mark Greene","Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"],["Joe Johnson"]],

"details":[["OFF"],["OFF"],["Gregory","OFF"],["Gregory"],["OFF"],["OFF"],["OFF"],["Weekday Rounders","OFF"],["Weekday Rounders","Night Owls"],["Gregory","OFF"],["Gregory","OFF"],["OFF"],["OFF"],["OFF"],["Gregory"],["Gregory","OFF"],["Gregory"],["Gregory","OFF"],["Gregory","OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"],["OFF"]]

更新

这是获取数据的 Alamofire 异步函数:

manager.request(.POST, getRouter(), parameters:["dev": 1, "app_action": "schedule", "type":getScheduleType(), "days_off":getScheduleDaysOff(), "period":getSchedulePeriod(), "begin_date":getScheduleBeginDate(), "end_date":getScheduleEndDate()])
        .responseString {response in
            print(response)
            var json = JSON(response.result.value!);
// what I'm missing
   }

【问题讨论】:

  • 您是如何从服务器获取这些数据的?一些框架内置了 JSON 解析器,可以让您轻松创建这些数组
  • @Thom 试试我的回答,如果你有问题请告诉我
  • @Thom 好的,如果它对你有用,请将我的答案标记为正确,我将不胜感激,谢谢

标签: ios arrays json uitableview swift2


【解决方案1】:

你可以使用这个功能:

func convertStringToDictionary(text: String) -> [String:AnyObject]? {
    if let data = text.dataUsingEncodi‌​ng(NSUTF8StringEncodi‌​ng) {
        do {
            return try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject]
        } catch let error as NSError {
            print(error)
        }
    }
    return nil
}

然后你可以像这样读取数组:

if let dict = convertStringToDictionary(jsonText) {
    let array = dict["headings"] as? [String]
}

【讨论】:

  • 我将函数放入一个 Swift 文件中,它给了我两个错误: 第 2 行:'String' 类型的值没有成员 'data' 第 4 行:使用未解析的标识符 'JSONSerialization'
  • @Thom 试试这个:let data = text.dataUsingEncoding(NSUTF8StringEncoding)
  • 修复了第一个错误。仍然在第 4 行获得。
  • @Thom 将 JSONSerialization 替换为 NSJSONSerialization
  • 我试过了,但后来它说 jsonObject 不是 NSJSONSerialization 的成员
【解决方案2】:

看起来您从 json 获取 Dictionary 并且每个键都包含 Array,您可以尝试这样的事情,首先声明一个 Dictionary 实例并将其与 TableViewDataSource 方法一起使用。

var response = [String: AnyObject]()

do {
     self.response = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! [String: AnyObject]
     print(dic)
}
catch let e as NSError {
     print(e.localizedDescription)
}

现在在 tableView 方法中

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    if let arr = self.response["headings"] as? [String] {
        return arr.count
    }
    return 0
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let headings = self.response["headings"] as! [String]
    return headings[Int]
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let arr = self.response["titles"] as? [[String]] {
        return arr[Int].count
    }
    return 0
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let titles = self.response["titles"] as! [[String]]
    let details = self.response["details"] as! [[String]]       
    let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! EmployeeCell
    cell.mainLabel?.text = titles[indexPath.section][indexPath.row]
    cell.detailLabel?.text = details[indexPath.section][indexPath.row]
    return cell
}

【讨论】:

  • 我在data! 中输入了什么?我在你的 do/catch 中遇到错误。
  • 在您的 api 调用中,您将获得 NSData 对象,您需要使用该方法传递该对象,如果您没有得到它,请添加您用来调用 api 的相关代码。
  • var json = JSON(response.result.value!);这一行之后添加这样的行 self.response = json as! [String: AnyObject]` 然后重新加载 tableView。
  • 你按照我说的尝试了吗?
  • 你是说我不需要 do/catch 吗?
【解决方案3】:

或者,您可以使用 JSON 解析库,例如 ArgoSwiftyJSON,它们是为了简化 JSON 解析而创建的。它们都经过了很好的测试,并且会为您处理边缘情况,例如 JSON 响应中缺少参数等。

使用 Argo 的示例:

假设 JSON 响应具有这种格式(来自Twitter API

{
  "users": [
    {
      "id": 2960784075,
      "id_str": "2960784075",
      ...
    }
}

1- 创建一个 Swift 类来表示响应

请注意,Response 是一个包含 User 数组的类,这是此处未显示的另一个类,但您明白了。

struct Response: Decodable {
    let users: [User]
    let next_cursor_str: String

    static func decode(j: JSON) -> Decoded<Response> {
        return curry(Response.init)
            <^> j <|| "users"
            <*> j <| "next_cursor_str"
    }
}

2- 解析 JSON

//Convert json String to foundation object
let json: AnyObject? = try? NSJSONSerialization.JSONObjectWithData(data, options: [])

//Check for nil    
if let j: AnyObject = json {
  //Map the foundation object to Response object
  let response: Response? = decode(j)
}

使用 Swifty 的示例

official documentation中所述:

1- 将 JSON 字符串转换为 SwiftyJSON 对象

if let dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
    let json = JSON(data: dataFromString)
}

2- 访问特定元素

如果数据是数组,则使用索引

//Getting a double from a JSON Array
let name = json[0].double

如果数据是字典,则使用键

//Getting a string from a JSON Dictionary
let name = json["name"].stringValue

2'- 循环遍历元素

数组

//If json is .Array
//The `index` is 0..<json.count's string value
for (index,subJson):(String, JSON) in json {
    //Do something you want
}

字典

//If json is .Dictionary
for (key,subJson):(String, JSON) in json {
   //Do something you want
}

【讨论】:

  • 谢谢。 Swifty怎么样?我查看了那里,但无法成功实现任何东西。
  • @Thom 引用了文档中的重要部分。请注意,您使用 Argo 创建一个类,然后让 Argo 将 JSON 数据映射到您的类,但在 Swifty 中,您无需创建类,而是您自己进行映射。
  • 这太棒了。谢谢你。我正在使用 SwiftyJson 并且能够使用它来迭代一维没有问题。字典基本上是 JS 对象吗?
  • 你的意思是相当于JS字典?是的,它是:)
【解决方案4】:

我建议使用 AlamofireObjectMapper。该库使您可以轻松地从 json 映射对象,如果与 Alamofire 结合使用,则可以在服务器响应中转换和返回您的对象。在您的情况下,对象映射本身应该是这样的

class CustomResponseClass: Mappable {
    var headings: [String]?

    required init?(_ map: Map){

    }

    func mapping(map: Map) {
        headings <- map["headings"]
   }
}

这样你就可以从你的 tableViewController 中解耦映射和解析 json 的逻辑。

AlamofireObjectMapper

【讨论】:

  • 谢谢。看看这个。
  • @Thom 如果您找到了解决方案,请您接受上述答案之一。
  • 我使用了多个答案中的点点滴滴,但我选择了我认为最接近我最终解决方案的一个。
猜你喜欢
  • 2016-05-13
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多