【问题标题】:The data couldn’t be read because it isn’t in the correct format. Swift 5无法读取数据,因为它的格式不正确。斯威夫特 5
【发布时间】:2021-05-04 07:59:16
【问题描述】:

我正在尝试解码来自https://swapi.dev/ 的数据。我使用响应代码 200 正确获取 json,但解码器无法读取数据,因为格式不正确。我尝试了很多不同的方式。我正在尝试获取有关人员的信息。

这是我的代码:

模型文件

struct people: Codable {
    let count: Int
    let next: String?
    let previous: String?
    let results: [result]
}

struct result: Codable{
    let name: String
    let height: Int
    let mass: Int
    let hair_color: String
    let skin_color: String
    let eye_color: String
    let birth_year: String
    let gender: String
    let homeworld: String
    let films: [String]
    let species: [String]
    let vehicles: [String]
    let starships: [String]
    let created: String
    let edited: String
    let url: String
    
}

struct APIError: Codable {
    let detail: String
}

网络服务


typealias OnApiSucces = (people) -> Void
typealias OnApiError = (String) -> Void

struct ApiService {
    static let shared = ApiService()
    
    let URL_BASE = "https://swapi.dev/api"
    let URL_PEOPLE = "/people"
    
    let session = URLSession(configuration: .default)
    

    
    func getResults(onSuccess: @escaping OnApiSucces, onError: @escaping OnApiError) {

        let url = URL(string: "\(URL_BASE)\(URL_PEOPLE)")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET" // GET, PUT, POST, DELETE for some different api
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        let task = session.dataTask(with: request) { (data, response, error) in

                if let error = error {
                    onError(error.localizedDescription)
                    return
                }

                guard let data = data, let response = response as? HTTPURLResponse else {
                    onError("Invalid data or response")
                    return
                }

                do{
                    if response.statusCode == 200 {
                        print("Code is \(response.statusCode)")
                        let results = try JSONDecoder().decode(people.self, from: data)
                        onSuccess(results)
                    } else {
                        let err = try JSONDecoder().decode(APIError.self, from: data)
                        print("Code is \(response.statusCode)")
                        onError(err.detail)
                    }
                }
                catch {
                    onError(error.localizedDescription)
                }

            }
        task.resume()

        }

    }

** 在 ViewController 上获取数据**

    func getResults() {
        ApiService.shared.getResults { (people) in
            self.results = people.results
        } onError: { (error) in
            debugPrint(error.description)
        }
    }

【问题讨论】:

  • 提示:将生成的 JSON 粘贴到 app.quicktype.io 以获取生成的模型结构
  • 永远不要在 JSONDecoder 捕获块中打印 error.localizedDescription,错误消息毫无意义。打印error,它向您展示了真正可理解的错误。在 JSON 中,用双引号括起来的所有内容都是 String 甚至是 "123""false"
  • 谢谢!我更改为 String,现在可以使用了。

标签: ios json swift api jsondecoder


【解决方案1】:

首先,您的数据无法读取,因为 heightmass 在 Star Wars API 中表示为 String,而您在 Codable 结构中将它们表示为 Int

另外,尝试将CodingKeys 添加到您的Codable 结构中,以便您的结构符合命名约定(特别是关于您的attribute_color 变体),例如

struct result: Codable{
    let name: String
    let height: String
    let mass: String
    let hairColor: String  // changed from hair_color
    let skinColor: String
    let eyeColor: String
    let birthYear: String
    let gender: String
    let homeworld: String
    let films: [String]
    let species: [String]
    let vehicles: [String]
    let starships: [String]
    let created: String
    let edited: String
    let url: String
    enums CodingKeys: String, CodingKey {
      case name = "name"
      case height = "height"
      case mass = "mass"
      case hairColor = "hair_color"
      case skinColor = "skin_color"
      case eyeColor = "eye_color"
      case birthYear = "birth_year"
      case gender = "gender"
      case homeworld = "homeworld"
      case films = "films"
      case species = "species"
      case vehicles = "vehicles"
      case starships = "starships"
      case created = "created"
      case edited = "edited"
      case url = "url" 
    }
}

【讨论】:

  • 或者,如果映射像这样简单,则使用JSONDecoder.KeyDecodingStrategy.convertFromSnakeCase
  • 将类型更改为字符串。
猜你喜欢
  • 2016-10-15
  • 1970-01-01
  • 2019-07-28
  • 2018-04-06
  • 2020-07-26
  • 2021-10-05
  • 2021-11-11
  • 2021-12-04
相关资源
最近更新 更多