如何在 Swift 5 中使用 Alamofire 解析 json
Posted
技术标签:
【中文标题】如何在 Swift 5 中使用 Alamofire 解析 json【英文标题】:How to parse json with Alamofire in Swift 5 【发布时间】:2019-11-14 11:21:21 【问题描述】:我是 ios 编程语言的新手,我正在尝试将数据从 WordPress JSON 提取到表格视图中。我遇到了错误:
'Any' 类型的值没有下标
当我尝试实例化数组的对象时。
这是 JSON:
[
"id": 1352,
"date": "2019-10-16T09:30:39",
"date_gmt": "2019-10-16T09:30:39",
"guid":
"rendered": "https://wepress.comm-it.it/ddjhgtr/"
,
"modified": "2019-10-16T13:23:41",
"modified_gmt": "2019-10-16T13:23:41",
"slug": "ddjhgtr",
"status": "publish",
"type": "post",
"link": "https://wepress.comm-it.it/ddjhgtr/",
"title": "ddjhgtr",
"content": "eryyreytyvggjggvhghhh",
"excerpt": "eryyreyty",
"author": 2,
"featured_media":
"id": 1418,
"url": "https://wepress.comm-it.it/wp-content/uploads/2019/10/10-62.jpeg"
,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
"id": 1,
"name": "Uncategorized",
"description": ""
],
"tags": [],
"_links":
"self": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts/1352"
],
"collection": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts"
],
"about": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/types/post"
],
"author": [
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/users/2"
],
"replies": [
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/comments?post=1352"
],
"version-history": [
"count": 3,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts/1352/revisions"
],
"predecessor-version": [
"id": 1419,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts/1352/revisions/1419"
],
"wp:featuredmedia": [
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/media/1418"
],
"wp:attachment": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/media?parent=1352"
],
"wp:term": [
"taxonomy": "category",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/categories?post=1352"
,
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/tags?post=1352"
,
"taxonomy": "difficulty-level-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/difficulty-level-course?post=1352"
,
"taxonomy": "category-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/category-course?post=1352"
,
"taxonomy": "location-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/location-course?post=1352"
,
"taxonomy": "duration-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/duration-course?post=1352"
],
"curies": [
"name": "wp",
"href": "https://api.w.org/rel",
"templated": true
]
,
....(许多其他新闻对象)
"id": 774,
"date": "2019-10-07T07:30:51",
"date_gmt": "2019-10-07T07:30:51",
"guid":
"rendered": "https://wepress.comm-it.it/name-here/"
,
"modified": "2019-10-07T07:30:51",
"modified_gmt": "2019-10-07T07:30:51",
"slug": "name-here",
"status": "publish",
"type": "post",
"link": "https://wepress.comm-it.it/name-here/",
"title": "name here",
"content": "desc here",
"excerpt": "desc here",
"author": 2,
"featured_media": null,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
"id": 1,
"name": "Uncategorized",
"description": ""
],
"tags": [],
"_links":
"self": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts/774"
],
"collection": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts"
],
"about": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/types/post"
],
"author": [
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/users/2"
],
"replies": [
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/comments?post=774"
],
"version-history": [
"count": 0,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/posts/774/revisions"
],
"wp:attachment": [
"href": "https://wepress.comm-it.it/wp-json/wp/v2/media?parent=774"
],
"wp:term": [
"taxonomy": "category",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/categories?post=774"
,
"taxonomy": "post_tag",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/tags?post=774"
,
"taxonomy": "difficulty-level-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/difficulty-level-course?post=774"
,
"taxonomy": "category-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/category-course?post=774"
,
"taxonomy": "location-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/location-course?post=774"
,
"taxonomy": "duration-course",
"embeddable": true,
"href": "https://wepress.comm-it.it/wp-json/wp/v2/duration-course?post=774"
],
"curies": [
"name": "wp",
"href": "https://api.w.org/rel",
"templated": true
]
]
目前我有兴趣获取这些“对象”的图像 (featured_media
)、标题和内容,并将它们放入 tableView
。事实上,这里是我为他们创建的结构:
新闻表示包含在 JSON 数组中的结构
struct News
public var id: Int
public var title: String
public var content: String
public var image: FeaturedMedia
struct FeaturedMedia
public var id: Int
public var url: String
这是UITableViewCell
类:
import UIKit
class NewsTableViewCell: UITableViewCell
@IBOutlet weak var newsImage: UIImageView!
@IBOutlet weak var newsTitle: UILabel!
@IBOutlet weak var newsContent: UILabel!
override func awakeFromNib()
super.awakeFromNib()
override func setSelected(_ selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
这里是UITableViewController
类:
import UIKit
import Alamofire
import Alamofire_SwiftyJSON
import SwiftyJSON
class NewsTableViewController: UITableViewController
var newsList: [News] = [News]()
func parseJsonNews()
DispatchQueue.main.async
Alamofire.request("link request", method: .get).responseJSON (response) in
switch response.result
case .success(let value):
let news = [value]
print(news) // here in console it prints correctly the json, starting with [<__NSArrayI 0x6000001a9e60 ....
for new in news
let title = new["title"]
print(title)
print(newsss)
self.tableView.reloadData()
case.failure(let error):
print(error.localizedDescription)
)
override func viewDidLoad()
super.viewDidLoad()
parseJsonNews()
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.newsList.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "newsCell", for: indexPath) as? NewsTableViewCell
// Configure the cell...
let imageUrl = URL.init(string: newsList[indexPath.row].featuredMedia.url)
cell?.newsTitle.text = self.newsList[indexPath.row].title
cell?.newsContent.text = self.newsList[indexPath.row].content
cell.newsImage.load(url: imageUrl!)
return cell!
extension UIImageView
func load(url: URL)
DispatchQueue.global().async [weak self] in
if let data = try? Data(contentsOf: url)
if let image = UIImage(data: data)
DispatchQueue.main.async
self?.image = image
寻找解决方案,我刚刚找到了许多解析字典 JSON 的方法,但在这种情况下,它是一个数组,所以我修改了您在 parseJsonNews
方法处阅读的代码,但它不能正常工作。
如果有任何帮助,将不胜感激。
【问题讨论】:
也许这对你有用 -> medium.com/better-programming/json-parsing-in-swift-2498099b78f 这一行打印什么?print(title)
你到底在哪一行得到错误?
您需要使用 JsonDecoder 来解析响应中的值。您采用的结构应该是可编码的,然后您可以使用 JSONDecoder 将它们解码到您的模型类中。如果您需要有关 JSONDecoder 代码的帮助,请告诉我。
@FaysalAhmed 不,它不打印任何东西
【参考方案1】:
您可以像这样使用Codable
进行解码:
let data = try? JSONDecoder().decode([DummyData].self, from: jsonData)
但首先,您的所有模型都必须符合Codable
协议。例如:
struct DummyData: Codable
let id: Int
let date, dateGmt: String
let modified, modifiedGmt, slug, status: String
let type: String
let link: String
let title, content, excerpt: String
let author: Int
let commentStatus, pingStatus: String
let sticky: Bool
let template, format: String
enum CodingKeys: String, CodingKey
case id, date
case dateGmt = "date_gmt"
case modified
case modifiedGmt = "modified_gmt"
case slug, status, type, link, title, content, excerpt, author
case commentStatus = "comment_status"
case pingStatus = "ping_status"
case sticky, template, format
【讨论】:
现在开始工作了!但是当我启动模拟器时,它正确设置了表格视图,但是当我滚动 tableView 时,行的高度会变大 这听起来像自动布局问题。我无能为力,因为我不知道细节,但 Apple 有一个关于 Auto Layout 的非常好的文档。 developer.apple.com/library/archive/documentation/… 您还可以在UITableViewDelegate
的heightForRowAt
函数中更改所有单元格的高度。 developer.apple.com/documentation/uikit/uitableviewdelegate/…【参考方案2】:
有几点:
错误value of type 'Any' has no subscripts
,指的是你的行let title = new["title"]
。
.success
枚举中Alamofire
的响应结果返回Any
的类型,
这适用于您获取的整个数据数组。
swift 中的Any
类型没有任何subscripts
实现(即:您不能使用以下语法obj['MY_VAR_NAME']
访问其中的变量。
为了像let title = new["title"]
这样从news
对象访问title
,您必须首先将对象转换为字典,可以这样完成:
// ...
let news = [value]
print(news)
for new in news
if let obj = new as? [String: Any]
let title = obj["title"]
print(title)
// ...
为了解析/使用您的自定义结构,它们必须首先遵守 swift 的Codable
协议。
/// Example show only News, but the same which be used for FeaturedMedia
struct News
public var id: Int
public var title: String
public var content: String
public var image: FeaturedMedia?
init?(jsonString: String)
guard let data = jsonString.data(using: .utf8) else
return nil
guard let object = News(data: data) else
return nil
self = object
init?(data: Data)
guard let object = try? JSONDecoder().decode(News.self, from:
data) else
return nil
self = object
// Optional, for custom key names (i.e: "image" instead of "featured_media"
private enum CodingKeys: String, CodingKey
case id = "id"
case image = "featured_media"
// etc..
完成第 4 步后,您可以像这样初始化对象:
// ...
let news = [value]
print(news)
for new in news
if let obj = News(new)
/// obj is now a News object
let title = obj.title
print(title)
// ...
如果您正在寻求更多信息(例如初始化整个数组) 退房this 我希望我已经把事情弄清楚了:)
【讨论】:
【参考方案3】: func ComplainData()
let semaphore = DispatchSemaphore(value: 0)
var request = URLRequest(url: URL(string: Constant.localBaseurl2 + "compID") !, timeoutInterval: Double.infinity)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request)
data,
response,
error in
if let response = response
let nsHTTPResponse = response as!HTTPURLResponse
print(nsHTTPResponse)
if let error = error
print("\(error)")
return
if let data = data
DispatchQueue.main.async
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase //or any other Decoder\
do
let jsonDecoder = JSONDecoder()
let memberRecord =
try jsonDecoder.decode(COMPLAINTSVC.GetComplaints.self, from: data)
print(memberRecord.message)
for detailData in memberRecord.message
print(detailData)
catch
print(error.localizedDescription)
semaphore.signal()
task.resume()
semaphore.wait()
【讨论】:
您应该为答案添加解释。How to parse json with Alamofire
你的回答中没有使用 Alamofire,这是题外话。以上是关于如何在 Swift 5 中使用 Alamofire 解析 json的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Alamofire 5.0.0-beta.3 (Swift 5) 上传图片(多部分)
如何在 swift 5 中使用 alamofire 对登录到我的 iOS 应用程序的用户进行身份验证?
如何在 Alamofire 中上传文件并在参数中传递数据 - swift 5
如何在 swift5 和 Alamofire 5 beta 版本中获取和保存响应?