【问题标题】:API Call & JSON DecodingAPI 调用和 JSON 解码
【发布时间】:2020-09-13 02:47:25
【问题描述】:

在尝试执行 API 请求并将后续 JSON 解码为数据字段时遇到错误。

目的是在应用程序内查询API并将数据映射到字典中,以便按国家/地区查询数据。

这里是 API 格式,不需要 API 密钥:

{
  "Global": {
    "NewConfirmed": 98206,
    "TotalConfirmed": 5492996,
    "NewDeaths": 3030,
    "TotalDeaths": 351576,
    "NewRecovered": 56379,
    "TotalRecovered": 2167913
  },
  "Countries": [
    {
      "Country": "Afghanistan",
      "CountryCode": "AF",
      "Slug": "afghanistan",
      "NewConfirmed": 584,
      "TotalConfirmed": 10582,
      "NewDeaths": 2,
      "TotalDeaths": 218,
      "NewRecovered": 35,
      "TotalRecovered": 1075,
      "Date": "2020-05-26T03:04:40Z"
    },
    {
      "Country": "Albania",
      "CountryCode": "AL",
      "Slug": "albania",
      "NewConfirmed": 9,
      "TotalConfirmed": 998,
      "NewDeaths": 1,..........

这是数据字段的结构,我认为我的问题出在哪里,但我是初学者,不确定正确的结构/格式:

struct GlobalSum: Decodable {
    let globalNC: Int
    let globalTC: Int
    let globalND: Int
    let globalTD: Int
    let globalNR: Int
    let globalTR: Int
    let sumByCntry: [CountrySum]

    enum CodingKeys: String, CodingKey {
        case globalNC = "NewConfirmed"
        case globalTC = "TotalConfirmed"
        case globalND = "NewDeaths"
        case globalTD = "TotalDeaths"
        case globalNR = "NewRecovered"
        case globalTR = "TotalRecovered"
        case sumByCntry = "Countries"
    }
}

struct CountrySum: Decodable {
    let Country: String
    let CountryCode: String
    let Slug: String
    let NewConfirmed: Int
    let TotalConfirmed: Int
    let NewDeaths: Int
    let TotalDeaths: Int
    let NewRecovered: Int
    let TotalRecovered: Int
    let Date: String

}

这里是 API 调用和 JSON 解码:

func getSummary() {
        let callString = "https://api.covid19api.com/summary"
        let urlCall = URL(string: callString)
        guard urlCall != nil else {
            print("Error reaching API")
            return
        }
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlCall!) { (data, response, error) in
            if error == nil && data != nil {
                let decoder = JSONDecoder()
                do {
                    let sumPull = try decoder.decode(GlobalSum.self, from: data!)
                    print(sumPull.globalNC)
                }
                catch {
                    print(error)               }
            }
        }
        dataTask.resume()
    }

这是错误:

dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})))

任何建议将不胜感激。为可能明显的错误道歉。刚刚开始使用 Swift 自学。

【问题讨论】:

  • 请发布完整的 json 文件?
  • 将您的 JSON 粘贴到 app.quicktype.io
  • 端点当前返回“您已达到最大请求限制。”,确实是无效的JSON

标签: json swift api dictionary


【解决方案1】:

像这样更新您的模型并尝试解析它。这是我的代码。

这是正确的结构:

import Foundation

struct Summary: Codable {
    let global: Global
    let countries: [Country]
    let date: String

    enum CodingKeys: String, CodingKey {
        case global    = "Global"
        case countries = "Countries"
        case date      = "Date"
    }
}

struct Country: Codable {
    let country, countryCode, slug: String
    let newConfirmed, totalConfirmed, newDeaths, totalDeaths: Int
    let newRecovered, totalRecovered: Int
    let date: String

    enum CodingKeys: String, CodingKey {
        case country        = "Country"
        case countryCode    = "CountryCode"
        case slug           = "Slug"
        case newConfirmed   = "NewConfirmed"
        case totalConfirmed = "TotalConfirmed"
        case newDeaths      = "NewDeaths"
        case totalDeaths    = "TotalDeaths"
        case newRecovered   = "NewRecovered"
        case totalRecovered = "TotalRecovered"
        case date           = "Date"
    }
}

struct Global: Codable {
    let newConfirmed, totalConfirmed, newDeaths, totalDeaths: Int
    let newRecovered, totalRecovered: Int

    enum CodingKeys: String, CodingKey {
        case newConfirmed   = "NewConfirmed"
        case totalConfirmed = "TotalConfirmed"
        case newDeaths      = "NewDeaths"
        case totalDeaths    = "TotalDeaths"
        case newRecovered   = "NewRecovered"
        case totalRecovered = "TotalRecovered"
    }
}

这里是 API 调用和 JSON 解码:

func getSummary() {
    let callString = "https://api.covid19api.com/summary"
    let urlCall = URL(string: callString)
    guard urlCall != nil else {
        print("Error reaching API")
        return
    }
    let session = URLSession.shared
    let dataTask = session.dataTask(with: urlCall!) { (data, response, error) in
        if error == nil && data != nil {
            let decoder = JSONDecoder()
            do {
                let sumPull = try decoder.decode(Summary.self, from: data!)
                print(sumPull.global)
            }
            catch {
                print(error)
            }
        }
    }
    dataTask.resume()
}

【讨论】:

    【解决方案2】:

    我从 json 中得到的 .. 你的模态应该是这样的

     struct CoronaCases {
            let global : GlobalSum
            let countries: CountrySum
            let date: String
    
            enum CodingKeys: String, CodingKey {
                case global = "Global"
                case countries = "Countries"
                case date = "Date"
    
            }
        }
    
        struct GlobalSum: Decodable {
            let globalNC: Int
            let globalTC: Int
            let globalND: Int
            let globalTD: Int
            let globalNR: Int
            let globalTR: Int
    
    
            enum CodingKeys: String, CodingKey {
                case globalNC = "NewConfirmed"
                case globalTC = "TotalConfirmed"
                case globalND = "NewDeaths"
                case globalTD = "TotalDeaths"
                case globalNR = "NewRecovered"
                case globalTR = "TotalRecovered"
    
            }
        }
        struct CountrySum: Decodable {
            let Country: String
            let CountryCode: String
            let Slug: String
            let NewConfirmed: Int
            let TotalConfirmed: Int
            let NewDeaths: Int
            let TotalDeaths: Int
            let NewRecovered: Int
            let TotalRecovered: Int
            let Date: String
    
        }
    

    然后

    let sumPull = try decoder.decode(CoronaCases.self, from: data!)
    

    这是由 app.quicktype.io 生成的

    import Foundation
    
    // MARK: - Welcome
    struct Welcome: Codable {
        let global: Global
        let countries: [Country]
        let date: Date
    
        enum CodingKeys: String, CodingKey {
            case global = "Global"
            case countries = "Countries"
            case date = "Date"
        }
    }
    
    // MARK: - Country
    struct Country: Codable {
        let country, countryCode, slug: String
        let newConfirmed, totalConfirmed, newDeaths, totalDeaths: Int
        let newRecovered, totalRecovered: Int
        let date: Date
    
        enum CodingKeys: String, CodingKey {
            case country = "Country"
            case countryCode = "CountryCode"
            case slug = "Slug"
            case newConfirmed = "NewConfirmed"
            case totalConfirmed = "TotalConfirmed"
            case newDeaths = "NewDeaths"
            case totalDeaths = "TotalDeaths"
            case newRecovered = "NewRecovered"
            case totalRecovered = "TotalRecovered"
            case date = "Date"
        }
    }
    
    // MARK: - Global
    struct Global: Codable {
        let newConfirmed, totalConfirmed, newDeaths, totalDeaths: Int
        let newRecovered, totalRecovered: Int
    
        enum CodingKeys: String, CodingKey {
            case newConfirmed = "NewConfirmed"
            case totalConfirmed = "TotalConfirmed"
            case newDeaths = "NewDeaths"
            case totalDeaths = "TotalDeaths"
            case newRecovered = "NewRecovered"
            case totalRecovered = "TotalRecovered"
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多