首页 > 解决方案 > 如何使用组合从 SwiftUI 中的 URL 解析单个 JSON 对象?

问题描述

目前,我正在尝试解析单个对象并将其解码,以便在我的 SwiftUI 视图中输出到 Text(),但我无法创建没有参数的实例。

我发现了许多用于动态创建列表的资源,但这只是一个独立的对象。很多资源都展示了如何使用数组创建 @Published 变量,但我只想要一个对象。

我构建的解码结构是:

// MARK: - Welcome
struct Welcome: Codable {
    let verse: Verse
}

// MARK: - Verse
struct Verse: Codable {
    let details: Details
    let notice: String
}

// MARK: - Details
struct Details: Codable {
    let text, reference, version: String
    let verseurl: String
}

我创建了以下提取器:

public class VerseFetcher: ObservableObject {
    @Published var verse = Welcome()

    init(){
        load()
    }

    func load() {
        let url = URL(string: "https://beta.ourmanna.com/api/v1/get/?format=json")!

        URLSession.shared.dataTask(with: url) {(data,response,error) in
            do {
                if let d = data {
                    let webData = try JSONDecoder().decode(Verse.self, from: d)
                    DispatchQueue.main.async {
                        self.verse = webData
                    }
                }else {
                    print("No Data")
                }
            } catch {
                print ("Error here")
            }

        }.resume()
    }
}

我已经尝试过这个解决方案来获得输出:

struct DailyVerseView: View {
    @ObservedObject var fetcher = VerseFetcher()

    var body: some View {

        Text(self.fetchVerse.todos.verse.details.text)
            .fontWeight(.semibold)
            .font(.caption)
            .foregroundColor(.secondary)
            .padding(.leading, 16)
            .padding(.trailing, 16)
            .padding(.top, 8)
            .padding(.bottom, 8)
    }
}

我从https://beta.ourmanna.com/api/v1/get/?format=json的 URL 读取的 JSON是:

{
  "verse": {
    "details": {
      "text": "The world and its desires pass away, but the man who does the will of God lives forever.",
      "reference": "1 John 2:17",
      "version": "NIV",
      "verseurl": "http://www.ourmanna.com/"
    },
    "notice": "Powered by OurManna.com"
  }
}

如何创建没有参数的 Verse 结构,因为它是来自 URL 响应的动态?

标签: jsonswiftswiftuicombine

解决方案


您的问题中提到的代码无法编译。为了使您的代码正常工作,我对您的代码进行了更改并添加了一些注释。

struct DailyVerseView: View {
    @ObservedObject var fetcher = VerseFetcher()
var body: some View {

    Text(self.fetcher.verse?.verse.details.text ?? "") // Changed fetchVerse to fetcher
        .fontWeight(.semibold)
        .font(.caption)
        .foregroundColor(.secondary)
        .padding(.leading, 16)
        .padding(.trailing, 16)
        .padding(.top, 8)
        .padding(.bottom, 8)
}}

public class VerseFetcher: ObservableObject {
@Published var verse: Welcome?

init(){
    load()
}

func load() {
    let url = URL(string: "https://beta.ourmanna.com/api/v1/get/?format=json")!

    URLSession.shared.dataTask(with: url) {(data,response,error) in
        do {
            if let d = data {
                //Decoding Welcome instead of Verse directly
                let webData = try JSONDecoder().decode(Welcome.self, from: d)
                DispatchQueue.main.async {
                    self.verse = webData
                }
            }else {
                print("No Data")
            }
        } catch {
            print ("Error here")
        }

    }.resume()
}}


// MARK: - Welcome
struct Welcome: Codable {
    let verse: Verse
}

// MARK: - Verse
struct Verse: Codable {
    let details: Details
    let notice: String
}

// MARK: - Details
struct Details: Codable {
    let text, reference, version: String
    let verseurl: String
}

推荐阅读