我试图解析从服务器收到的数据,以便将其显示在UIPicker视图中。但是我解析它并将其显示到UIPIcker View中太复杂了。什么是最好的方法,我可以解析以下数据,并为UIPickerView
做好准备。
这是试图解析服务器信息的会话
let url = NSURL(string: "http://dummy.com/api")!
let request = URLRequest(url: url as URL)
URLSession.shared.dataTask(with: request) { data, response, error in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
guard let parseJSON = json else{
print("Error While Parsing")
return
}
print(parseJSON)
let responseDic = parseJSON["response"] as? NSDictionary
let utilityCode = responseDic?["utility_code"] as? String
if utilityCode == "AFRICELL" {
let africellPackages = responseDic?["packages"] as! NSArray
print(africellPackages)
}
}catch{
return
}
}
}.resume()
以下数据是发出GET请求时服务器的响应。
{
"status": "OK",
"response": [
{
"utility_code": "AIRTEL",
"packages": [
{
"package_id": 33,
"package_name": "Daily 10MB",
"package_code": "6000",
"package_price": 300
},
{
"package_id": 34,
"package_name": "Daily 20MB",
"package_code": "6002",
"package_price": 500
},
{
"package_id": 65,
"package_name": "Weekly Roaming 200MB",
"package_code": "6030",
"package_price": 100000
}
]
},
{
"utility_code": "AFRICELL",
"packages": [
{
"package_id": 68,
"package_name": "Daily 10 MB",
"package_code": "5000",
"package_price": 290
}
]
},
{
"utility_code": "SMART",
"packages": [
{
"package_id": 69,
"package_name": "Daily 50 MB",
"package_code": "8000",
"package_price": 500
}
]
},
{
"utility_code": "SMILE",
"packages": [
{
"package_id": 70,
"package_name": "Smile 1GB",
"package_code": "7006",
"package_price": 32000
}
]
}
]
}
干杯并感谢您的帮助!
答案 0 :(得分:0)
为简洁起见,提供以下所有示例而不进行错误检查。对于生产代码,您应该正确处理错误。
手动解码JSON的大部分工作涉及定义数据模型:
struct JSONResponse {
var status: String
var response: [Utility]
init(jsonDict: [String: AnyObject]) {
self.status = jsonDict["status"] as! String
self.response = [Utility]()
let response = jsonDict["response"] as! [AnyObject]
for r in response.map({ $0 as! [String: AnyObject] }) {
let utility = Utility(jsonDict: r)
self.response.append(utility)
}
}
}
struct Utility {
var code: String
var packages: [Package]
init(jsonDict: [String: AnyObject]) {
self.code = jsonDict["utility_code"] as! String
self.packages = [Package]()
let packages = jsonDict["packages"] as! [AnyObject]
for p in packages.map({ $0 as! [String: AnyObject] }) {
let package = Package(jsonDict: p)
self.packages.append(package)
}
}
}
struct Package {
var id: Int
var name: String
var code: String
var price: Int
init(jsonDict: [String: AnyObject]) {
self.id = jsonDict["package_id"] as! Int
self.name = jsonDict["package_name"] as! String
self.code = jsonDict["package_code"] as! String
self.price = jsonDict["package_price"] as! Int
}
}
以及如何使用它:
let jsonDict = try! JSONSerialization.jsonObject(with: data) as! [String: AnyObject]
let jsonResponse = JSONResponse(jsonDict: jsonDict)
let utilities = jsonResponse.response
print(utilities)
解码JSON是标准Swift的痛苦。您需要一个外部JSON框架,如ObjectMapper
,以减轻JSON数据和数据模型之间映射的痛苦。从CocoaPod或Carthage安装ObjectMapper
。
首先,在单独的文件中定义您的数据模型:
import ObjectMapper
struct JSONResponse : Mappable {
var status: String?
var response: [Utility]?
init?(map: Map) { }
mutating func mapping(map: Map) {
self.status <- map["status"]
self.response <- map["response"]
}
}
struct Utility : Mappable {
var code: String?
var packages: [Package]?
init?(map: Map) { }
mutating func mapping(map: Map) {
self.code <- map["code"]
self.packages <- map["packages"]
}
}
struct Package : Mappable {
var id: Int?
var name: String?
var code: String?
var price: Int?
init?(map: Map) { }
mutating func mapping(map: Map) {
self.id <- map["package_id"]
self.name <- map["package_name"]
self.code <- map["package_code"]
self.price <- map["package_price"]
}
}
然后你可以使用它将JSON映射到你的对象:
// data is what your get in the dataTask's completion block
let jsonString = String(data: data, encoding: .utf8)!
if let jsonResponse = JSONResponse(JSONString: jsonString),
let utilities = jsonResponse.response {
print(utilities)
}
所有内容都必须声明为可选项,因为您不知道该值是否在JSON字符串中。
使用新的Encodable
和Decodable
协议,Swift 4中的事情变得更加简单。两者结合形成Encodable
协议(是的,protocol composition是Swift 4中的新事物)。你不再需要Swift 4中的ObjectMapper
。
您仍需要首先定义数据模型:
struct JSONResponse : Codable {
var status: String
var response: [Utility]
}
struct Utility : Codable {
var code: String
var packages: [Package]
private enum CodingKeys: String, CodingKey {
case code = "utility_code"
case packages
}
}
struct Package : Codable {
var id: Int
var name: String
var code: String
var price: Int
private enum CodingKeys: String, CodingKey {
case id = "package_id"
case name = "package_name"
case code = "package_code"
case price = "package_price"
}
}
以下是在Swift 4中使用新JSONDecoder
结构的方法:
let jsonRepsonse = try! JSONDecoder().decode(JSONResponse.self, from: data)
let utilities = jsonRepsonse.response
print(utilities)
ObjectMapper
和Codable
都将JSON中的值映射到您的数据模型。
在ObjectMapper
中,您必须明确列出哪个属性映射到名为mapping(map:)
的函数中JSON中的哪个值:
mutating func mapping(map: Map) {
self.id <- map["package_id"]
self.name <- map["package_name"]
self.code <- map["package_code"]
self.price <- map["package_price"]
}
<-
是&#34;映射运算符&#34;由ObjectMapper
定义(它不在标准库中)。
使用Swift 4&#39; Codable
,编译器会为你自动化很多东西,这使得它一开始看起来很神奇而且令人困惑。基本上,您在名为CodingKeys
的枚举中定义映射:
struct JSONResponse : Codable {
var status: String
var response: [Utility]
// Define your JSON mappings here
private enum CodingKeys: String, CodingKey {
case status = "status"
case response = "response"
}
}
struct Package : Codable {
var id: Int
var name: String
var code: String
var price: Int
// Define your JSON mappings here
private enum CodingKeys: String, CodingKey {
case id = "package_id"
case name = "package_name"
case code = "package_code"
case price = "package_price"
}
}
如果您的JSON键与您的属性名称相同,就像在JSONResponse
结构中一样,您不必为每个case
定义显式值,您只需编写:
struct JSONResponse : Codable {
var status: String
var response: [Utility]
private enum CodingKeys: String, CodingKey {
case status // no explicit value here
case response
}
}
更好的是,由于每个JSON键与您的属性名称相同,您可以一起省略CodingKeys
枚举,让编译器为您处理:
// All you need to do is to conform it to Codable
// CodingKeys is generated automatically
struct JSONResponse : Codable {
var status: String
var response: [Utility]
}
要详细了解Codable
,请观看2017年WWDC的What's new in Foundation会话。