首页 > 解决方案 > SwiftUI 从 URL 和构建列表中解析多层 JSON 数据

问题描述

首先是一个信息:我实际上正在学习swiftUI,我是一个新手。对于我的第一个项目,我决定创建一个从 joomla 网站加载文章的小应用程序。我的 API 将以以下结构响应查询:

{
"source": "my AppConnector for Joomla!",
"offset": 0,
"count": 0,
"results": [
    {
        "id": "8",
        "title": "Article 1",
        ...
    },
    {
        "id": "8",
        "title": "Article 2",
        ...
    }
]

}

将来,API 将返回更复杂的结构,但实际上我已经在努力解决这个问题。我发现的所有 swiftUI 示例和视频都只是解释如何检索项目数组或过时并显示 depreacet 代码示例(使用一维示例我已经成功创建了项目的列表视图,但这不是我的想)。

我创建了以下结构:

struct Welcome: Codable {
    let source: String
    let offset, count: Int
    let results: [Result]
}


// MARK: - Result
struct Result: Codable {
    let id, title, alias, introtext: String
    let fulltext, state, catid, created: String
    let createdBy, createdByAlias, modified, modifiedBy: String
    let checkedOut, checkedOutTime, publishUp, publishDown: String
    let images, urls, attribs, version: String
    let ordering, metakey, metadesc, access: String
    let hits, metadata, featured, language: String
    let xreference, note, slug, articleID: String
    let introImage, fullImage: String
}

和以下提取器:

import Foundation
import SwiftUI
import Combine


public class ArticlesFetcher: ObservableObject {
    @Published var articles = [Welcome]()
    
    init(){
        load()
    }
    
    func load() {
        let url = URL(string: "https://nx-productions.ch/index.php/news")! //This is a public demo url feel free to check the jsondata (SecurityToken temporary disabled)
    
        URLSession.shared.dataTask(with: url) {(data,response,error) in
            do {
                if let d = data {
                    let decodedLists = try JSONDecoder().decode([Welcome].self, from: d)
                    DispatchQueue.main.async {
                        self.articles = decodedLists
                    }
                }else {
                    print("No Data")
                }
            } catch {
                print ("Error")
            }
            
        }.resume()
         
    }
}

我的观点是这样的:

struct ContentView: View {

    @ObservedObject var fetcher = ArticlesFetcher()
    
    var body: some View {
        VStack {
            List(fetcher.articles.results) { article in
                VStack (alignment: .leading) {
                    Text(article.title)
                    Text(article.articleId)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                }
            }
        }
    }
}

我不明白的是视图部分-我无法指向字段,在上面的示例中我得到编译器错误,例如“类型'[欢迎]'的值没有成员'结果'”“值类型'Int'没有成员'title'”

我想我可能只是不了解我的结构或如何循环它。感谢您的任何建议。

标签: swiftuiswiftui-list

解决方案


JSON 以 a 开头,{所以它是一个字典。而且类型articles不对。

代替

@Published var articles = [Welcome]()

@Published var articles = [Result]()

并更换

let decodedLists = try JSONDecoder().decode([Welcome].self, from: d)
DispatchQueue.main.async {
   self.articles = decodedLists
}

let decodedLists = try JSONDecoder().decode(Welcome.self, from: d)
DispatchQueue.main.async {
   self.articles = decodedLists.results
}

最后但不相关的替换无意义

print ("Error")

print(error)

推荐阅读