简体   繁体   English

为什么 JSONDecoder 总是为可选属性返回 nil?

[英]Why JSONDecoder always returns nil for an optional property?

I get JSON one of the keys in which can be nil .我得到 JSON 可以为nil的键之一。 So, I use an optional property in the data model, but after decoding, I always get nil for this property, even if in JSON the value by key contained a string and not nil .因此,我在数据 model 中使用了一个可选属性,但在解码后,我总是得到这个属性的nil ,即使在 JSON 中,键值包含一个字符串而不是nil Below is the response I get and the output to the console, where I check what value is written to the profilePath property下面是我得到的响应和 output 到控制台,在那里我检查写入profilePath属性的值

Response:回复:

{"adult":false,"gender":2,"id":544002,"known_for_department":"Acting","name":"Giulio Berruti","original_name":"Giulio Berruti","popularity":2.467, "profile_path":"/ktPKniWGVkm6eBG7a2R7WGd96kZ.jpg" ,"cast_id":1,"character":"Gabriel Emerson","credit_id":"5fdad9cfeda4b70041400df3","order":1},{"adult":false,"gender":0,"id":2897282,"known_for_department":"Acting","name":"Rhett Wellington","original_name":"Rhett Wellington","popularity":0.6, "profile_path":null ,"cast_id":2,"character":"Simon Talbot","credit_id":"5fdad9dd3f7e1d004042f859","order":2} {"adult":false,"gender":2,"id":544002,"known_for_department":"Acting","name":"Giulio Berruti","original_name":"Giulio Berruti","popularity":2.467 , "profile_path":"/ktPKniWGVkm6eBG7a2R7WGd96kZ.jpg" ,"cast_id":1,"character":"Gabriel Emerson","credit_id":"5fdad9cfeda4b70041400df3","order":1},{"adult":false,"性别":0,"id":2897282,"known_for_department":"代理","name":"Rhett Wellington","original_name":"Rhett Wellington","受欢迎程度":0.6, "profile_path":null ," cast_id":2,"character":"Simon Talbot","credit_id":"5fdad9dd3f7e1d004042f859","order":2}

Console output:控制台 output:

控制台输出

func getMovieCredits(movieID: String, completion:@escaping (MovieCreditResponse) -> ()){
        guard let url = URL(string: "https://api.themoviedb.org/3/movie/\(movieID)/credits?api_key=<api_key>") else { return }
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            print("JSON String: \(String(data: data!, encoding: .utf8))") //checking response
            let movies = try! JSONDecoder().decode(MovieCreditResponse.self, from: data!)
            
            for cast in movies.cast {
                print("Profile path - " + (cast.profilePath ?? "nil")) //checking profilePath property
            }
            
            DispatchQueue.main.async {
                completion(movies )
            }
        }
        .resume()
    }
struct MovieCreditResponse: Codable {
    let cast: [MovieCast]
}

struct MovieCast: Identifiable, Codable {
    let id: Int
    let character: String
    let name: String
    let profilePath: String?
}

The property name in your JSON file is profile_path , but you try to decode it as profilePath . JSON 文件中的属性名称是profile_path ,但您尝试将其解码为profilePath You should add an enum to define JSON keys, like您应该添加一个枚举来定义 JSON 键,例如

enum CodingKeys: String, CodingKey {
    case profilePath = "profile_path"
    // add the other keys as well
}

The key in your JSON for profilePath property is profile_path .您的 JSON 中profilePath属性的键是profile_path So you can simply set keyDecodingStrategy property of your JSONDecoder to .convertFromSnakeCase and the decoding will be correct:因此,您可以简单地将.convertFromSnakeCasekeyDecodingStrategy属性设置为JSONDecoder并且解码将是正确的:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
    let movies = try JSONDecoder().decode(MovieCreditResponse.self, from: data!)
} catch {
    // Handle error
    print(error)
}

Also, generally it's really bad practice to use try!此外,通常使用try! . . You should do-try-catch instead and handle any thrown errors.您应该改为do-try-catch并处理任何抛出的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM