将 JSON 转换为 Swift 中的数组 2
Converting JSON to array in Swift 2
我需要为分组 UITableView
构建 Arrays
,每个 table 单元格中都有标题和详细信息行。我从服务器获得了我的 json 输出,将其置于正确的形状以循环访问 UITableViewDataSource
方法。但是,将这些转换为那些 UITableView
函数可以引用的可读数组的最简单方法是什么?
标题数组用于组标题,因此它只是一个 one-dimensional 数组。我可以重复那个。标题和详细信息数组都是二维的。我不知道如何在 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
}
您可以使用这个功能:
func convertStringToDictionary(text: String) -> [String:AnyObject]? {
if let data = text.dataUsingEncoding(NSUTF8StringEncoding) {
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]
}
看起来你从 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
}
或者,您可以使用 JSON 解析库,例如 Argo or SwiftyJSON,创建这些库是为了简化 JSON 解析。它们都经过了良好的测试,可以为您处理边缘情况,例如 JSON 响应中缺少参数等。
使用 Argo 的示例:
假设 JSON 响应具有这种格式(来自 Twitter API)
{
"users": [
{
"id": 2960784075,
"id_str": "2960784075",
...
}
}
1- 创建一个Swift class 来表示响应
请注意,Response
是一个 class,其中包含一个 User
数组,这是另一个 class,此处未显示,但您明白了。
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
}
我建议使用 AlamofireObjectMapper。该库使您可以轻松地映射来自 json 的对象,如果与 Alamofire 结合使用,可以在服务器响应上投射和 return 您的对象。在你的情况下,对象映射本身应该是这样的
class CustomResponseClass: Mappable {
var headings: [String]?
required init?(_ map: Map){
}
func mapping(map: Map) {
headings <- map["headings"]
}
}
通过这种方式,您可以将 json 的映射和解析逻辑与 tableViewController 分离。
我需要为分组 UITableView
构建 Arrays
,每个 table 单元格中都有标题和详细信息行。我从服务器获得了我的 json 输出,将其置于正确的形状以循环访问 UITableViewDataSource
方法。但是,将这些转换为那些 UITableView
函数可以引用的可读数组的最简单方法是什么?
标题数组用于组标题,因此它只是一个 one-dimensional 数组。我可以重复那个。标题和详细信息数组都是二维的。我不知道如何在 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
}
您可以使用这个功能:
func convertStringToDictionary(text: String) -> [String:AnyObject]? {
if let data = text.dataUsingEncoding(NSUTF8StringEncoding) {
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]
}
看起来你从 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
}
或者,您可以使用 JSON 解析库,例如 Argo or SwiftyJSON,创建这些库是为了简化 JSON 解析。它们都经过了良好的测试,可以为您处理边缘情况,例如 JSON 响应中缺少参数等。
使用 Argo 的示例:
假设 JSON 响应具有这种格式(来自 Twitter API)
{
"users": [
{
"id": 2960784075,
"id_str": "2960784075",
...
}
}
1- 创建一个Swift class 来表示响应
请注意,Response
是一个 class,其中包含一个 User
数组,这是另一个 class,此处未显示,但您明白了。
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
}
我建议使用 AlamofireObjectMapper。该库使您可以轻松地映射来自 json 的对象,如果与 Alamofire 结合使用,可以在服务器响应上投射和 return 您的对象。在你的情况下,对象映射本身应该是这样的
class CustomResponseClass: Mappable {
var headings: [String]?
required init?(_ map: Map){
}
func mapping(map: Map) {
headings <- map["headings"]
}
}
通过这种方式,您可以将 json 的映射和解析逻辑与 tableViewController 分离。