簡體   English   中英

如何在 Swift 5 中使用 Alamofire 解析 json

[英]How to parse json with Alamofire in Swift 5

我是 iOS 編程語言的新手,我正在嘗試從 WordPress JSON 中獲取數據到表視圖中。 我遇到了錯誤:

'Any' 類型的值沒有下標

當我嘗試實例化數組的 object 時。

這是 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 class:

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 class:

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方法中閱讀的代碼,但它不能正常工作。

將不勝感激任何幫助。

您可以像這樣使用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
    }
}

有幾件事:

  1. value of type 'Any' has no subscripts ,指的是你的行let title = new["title"] .success枚舉中Alamofire的響應結果返回Any類型,這對於您獲取的整個數據數組都是正確的。 swift 中的Any類型沒有任何subscripts實現(即:您不能使用以下語法訪問其中的變量obj['MY_VAR_NAME']

  2. 為了從您的news object 中訪問title ,就像let title = new["title"]一樣,您必須首先將對象轉換為字典,可以這樣完成:

     //... let news = [value] print(news) for new in news { if let obj = new as? [String: Any] { let title = obj["title"] print(title) } } //...
  3. 為了解析/使用您的自定義結構,它們必須首先遵守 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 (ie: "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)
                }
            }
            // ...

如果您正在尋求更多信息(例如初始化整個數組),請查看這個我希望我已經清理了一切:)

 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()
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM