【问题标题】:How to make a swift Codable struct for the following json data ( I am using URLSession.dataTask in Swiftui to get the data)?如何为以下 json 数据制作一个 swift Codable 结构(我在 Swiftui 中使用 URLSession.dataTask 来获取数据)?
【发布时间】:2021-10-17 06:22:00
【问题描述】:

我的 iOS 应用程序需要来自 World Bank API 的数据(我正在使用 SwiftUI)。一些 API 调用的 json 数据以大括号 ({}) 开始和结束,为此创建一个 Swift Codable 结构很简单。

但是,一些 API 调用返回以方括号 ([]) 开头的 JSON 数据,因此是几个字典的列表。我不知道如何为此构造一个快速的 Codable 结构。请帮帮我。我目前正在将它作为 jsonString 导入并执行拆分和其他几个操作以获得所需的格式,但是由于 json 数据很长,这种方法非常繁琐且耗时。

下面给出了我需要帮助制作 Swift Codable 结构的 json 数据示例:

[{"page":1,"pages":16226,"per_page":1,"total":16226,"sourceid":"2","sourcename":"世界发展指标","lastupdated" :"2021-07-30"},[{"indicator":{"id":"AG.AGR.TRAC.NO","value":"农业机械、拖拉机"},"country":{"id ":"ZH","value":"非洲东部和南部"},"countryiso3code":"AFE","date":"2020","value":null,"unit":"","obs_status" :"","十进制":0}]]

下面给出了我正在使用的实际数据的链接(我只是在这里复制并粘贴了其中的一部分,因为原始数据要长得多): http://api.worldbank.org/v2/country/all/indicator/AG.AGR.TRAC.NO?format=json&per_page=32500

【问题讨论】:

  • 复制并粘贴 json 数据到 "quicktype.io" 并使用它来生成你的数据结构。
  • 我不知道这个网站。非常感谢@workingdog 的提示! +
  • 我尝试使用通过 QuickType.io 制作的结构,但是在获取数据后与 JsonDecoder 一起使用时,它会引发错误

标签: json swift api


【解决方案1】:

您收到一个包含不同数据类型的数组:在您的示例中是一个“对象”,然后是一个数组。

该对象包含有关响应本身的信息(页数等Metadata)。该数组包含记录本身 ([ApiRecord]) 应该给这种模型什么(简化):

struct Metadata: Codable {
    let page: Int
    let sourceid: String
}

struct ApiRecord: Codable {
    let indicator: Indicator
    let country: Country
    let decimal: Int
}
struct Country: Codable {
    let id, value: String
}

struct Indicator: Codable {
    let id, value: String
}

现在,为了您的回复,我们将定义一个枚举(带有相关值)。 您的 api 响应将被解码为一组不同的枚举案例(关联值:元数据或 [ApiRecord]。

typealias ApiResponse = [ReponseType]

enum ReponseType: Codable {
    case metadata(Metadata)
    case apiRecordArray([ApiRecord])

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let record = try? container.decode([ApiRecord].self) {
            self = .apiRecordArray(record)
            return
        }
        if let record = try? container.decode(Metadata.self) {
            self = .metadata(record)
            return
        }
        throw DecodingError.typeMismatch(ReponseType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Error"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .metadata(let record):
            try container.encode(record)
        case .apiRecordArray(let record):
            try container.encode(record)
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多