我正在使用Xcode 9.2和Swift 4.如何检查返回的json数据是否为空?
现在它在行Type 'Any' has no subscript members
if json[0]["data"]
var json: NSMutableArray = []
var newsArray: NSMutableArray = []
let url = URLFactory()
var data = try! NSData(contentsOf: url.getURL()) as Data
do {
json = try JSONSerialization.jsonObject(with: data, options: []) as! NSMutableArray
if json[0]["data"] {
// data is not null
}
} catch let error as NSError {
// handle error
}
我的JSON返回如下内容:
{
"data":
[
{
"news_id":123,
"title":"title",
"news_date":"2017-02-08 21:46:06",
"news_url":"url",
"short_description":"description",
"category_id":4,
"category_name":"Health",
"latlng":
[
{
"lat":"43.003429",
"lng":"-78.696335"
}
]
}
{ ....
}
答案 0 :(得分:14)
如果你使用的是Swift 4,我可能会建议JSONDecoder
:
首先,定义用于保存已解析数据的类型:
struct ResponseObject: Codable {
let data: [NewsItem]
}
struct NewsItem: Codable {
let newsId: Int
let title: String
let newsDate: Date
let newsURL: URL
let shortDescription: String
let categoryID: Int
let categoryName: String
let coordinates: [Coordinate]
// because your json keys don't follow normal Swift naming convention, use CodingKeys to map these property names to JSON keys
enum CodingKeys: String, CodingKey {
case newsId = "news_id"
case title
case newsDate = "news_date"
case newsURL = "news_url"
case shortDescription = "short_description"
case categoryID = "category_id"
case categoryName = "category_name"
case coordinates = "latlng"
}
}
struct Coordinate: Codable {
let lat: String
let lng: String
}
然后你可以解析它:
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
let responseObject = try decoder.decode(ResponseObject.self, from: data)
print(responseObject.data)
} catch {
print(error)
}
显然,如果您的JSON不同,您可能需要相应地更改对象(例如,latlng
是一个坐标数组,这让我很奇怪)。此外,如果要将其中一些字符串转换为数字,则可以定义自定义init(from:)
方法,但我宁愿修复JSON,而是(为什么latlng
返回字符串值而不是数值)
有关详细信息,请参阅Encoding and Decoding Custom Types。
顺便说一下,我建议不要使用这种模式(请注意,这是您的网络请求逻辑,但已删除NSData
):
let data = try! Data(contentsOf: url.getURL())
那将同步检索数据,这可能会有问题,因为
我建议使用URLSession
:
let task = URLSession.shared.dataTask(with: url.getURL()) { data, _, error in
guard let data = data, error == nil else {
print(error ?? "Unknown error")
return
}
// now parse `data` like shown above
// if you then need to update UI or model objects, dispatch that back
// to the main queue:
DispatchQueue.main.async {
// use `responseObject.data` to update model objects and/or UI here
}
}
task.resume()