由于缺少Content-Type,因此无法解码JSON

时间:2019-02-02 14:14:17

标签: ios swift swift4 nsurlsession codable

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

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

我的代码:

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
}

我的实体(LivePhoto):

{{1}}

响应头:

response headers

正确的响应(另一个API):

correct response

3 个答案:

答案 0 :(得分:2)

您需要使用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块中,因此您可以知道错误并进行修复,这里没有信号量的地方,这只是完成工作,也是您可能会显示一个活动指示器,直到请求以更好的用户体验结束为止

答案 1 :(得分: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
}

答案 2 :(得分:2)

该错误与内容类型无关。

解码错误不是描述性的,而不是忽略catch print 中的错误。

} 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 \”)。“,底层错误: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。无论如何,使用完备处理程序毫无意义。