[英]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:因此,您可以简单地将.convertFromSnakeCase
的keyDecodingStrategy
属性设置为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.