【问题标题】:Can't decode JSON because Content-Type missed无法解码 JSON,因为缺少 Content-Type
【发布时间】:2019-02-02 14:14:17
【问题描述】:

我的 JSONDecoder().decode 无法将数据解码为 json 格式,因为服务器响应的 Content-Type 类似于“* \ *;charset=utf8”。

在这种情况下我该怎么办?有任何想法吗? API link

我的代码:

private static let livePhotoUrlString = "https://m1.kappboom.com/livewallpapers/info?o=0&v=575"

static func getLivePhotos(completionHandler: @escaping (([LivePhoto]) -> Void)) {
    guard let livePhotoUrl = URL(string: livePhotoUrlString) else { return }
    let semaphore = DispatchSemaphore(value: 0)

    URLSession.shared.dataTask(with: livePhotoUrl) { (data, response, error) in
         do {
             guard let data = data else { return }
             let livePhotos = try JSONDecoder().decode([LivePhoto].self, from: data)
             completionHandler(livePhotos)
         } catch {
             completionHandler([])
         }
         semaphore.signal()
     }.resume()
     semaphore.wait()
}

我的实体(LivePhoto):

class LivePhoto: Decodable {

    init(smallUrl: String, largeUrl: String, movieUrl: String, id: Int, isLocked: Bool, promotionalUnlock: Bool) {
        self.smallUrl = smallUrl
        self.largeUrl = largeUrl
        self.movieUrl = movieUrl
        self.id = id
        self.isLocked = isLocked
        self.promotionalUnlock = promotionalUnlock
    }

    var smallUrl: String
    var largeUrl: String
    var movieUrl: String
    var id: Int
    var isLocked: Bool
    var promotionalUnlock: Bool
}

响应标头:

正确响应(另一个 API):

【问题讨论】:

    标签: ios swift swift4 nsurlsession codable


    【解决方案1】:

    错误与内容类型无关。

    与其忽略catch块中的错误打印它,解码错误非常具有描述性。

    } catch {
        print(error)
        completionHandler([])
    }
    

    说明

    keyNotFound(CodingKeys(stringValue: "smallUrl", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "没有与键关联的值CodingKeys(stringValue: \"smallUrl\", intValue: nil) (\"smallUrl\").", underlyingError: nil))

    您可以立即看到键是small_url,而您的结构成员是smallUrl

    最简单的解决方案是添加convertFromSnakeCase密钥解码策略

    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let livePhotos = try decoder.decode([LivePhoto].self, from: data)
    

    而且你不需要类中的init 方法。将其声明为具有常量成员的结构

    struct LivePhoto: Decodable {
        let smallUrl, largeUrl, movieUrl: String
        let id: Int
        let isLocked: Bool
        let promotionalUnlock: Bool
    }
    

    请删除这个可怕的semaphore。无论如何,您都在使用完成处理程序,这是毫无意义的。

    【讨论】:

    • 感谢您的回答,它有帮助。
    【解决方案2】:

    您确定这是问题所在吗?在我看来您需要为您的结构定义编码键

    enum CodingKeys: String, CodingKey {
        case smallUrl = "small_url"
        case largeUrl = "large_url"
        case movieUrl = "movie_url"
        case isLocked = "is_locked"
        case promotionalUnlock = "promotional_unlock"
        case id
    }
    

    【讨论】:

      【解决方案3】:

      您需要使用 json 中的键名,或者使用转换后的名称编写一个枚举,但最好使用convertFromSnakeCase

        func getLivePhotos(completionHandler: @escaping (([LivePhoto]) -> Void)) {
              guard let livePhotoUrl = URL(string: livePhotoUrlString) else { return }
      
              URLSession.shared.dataTask(with: livePhotoUrl) { (data, response, error) in
                    print(data)
                  do {
                      guard let data = data else { return }
                      let dec = JSONDecoder()
                      dec.keyDecodingStrategy = .convertFromSnakeCase
                      let livePhotos = try dec.decode([LivePhoto].self, from: data)
                      completionHandler(livePhotos)
                  } catch {
                      print(error)
                      completionHandler([])
                  }
      
                  }.resume()
      
          }
      
      
      
      }
      

      struct LivePhoto: Codable {
          let id: Int
          let smallUrl, largeUrl: String
          let movieUrl: String
          let isLocked, promotionalUnlock: Bool
      
      }
      

      此外,最好将print(error) 始终放在catch 块内,这样你就可以知道错误并修复,这里没有信号量的地方,它只是完成的工作,你也可以显示一个活动指示器,直到请求作为更好的 UX 完成

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多