为什么 JSONDecoder 对于可选的 属性 总是 returns nil?
Why JSONDecoder always returns nil for an optional property?
我得到 JSON 其中一个键可以是 nil
。所以,我在数据模型中使用了一个可选的 属性,但是在解码之后,我总是得到 nil
这个 属性,即使在 JSON 中,键值包含一个字符串而不是 nil
。下面是我得到的响应和控制台的输出,我在其中检查写入 profilePath
属性
的值
响应:
{"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}
控制台输出:
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?
}
JSON 文件中的 属性 名称是 profile_path
,但您尝试将其解码为 profilePath
。
您应该添加一个枚举来定义 JSON 键,例如
enum CodingKeys: String, CodingKey {
case profilePath = "profile_path"
// add the other keys as well
}
JSON 中 profilePath
属性 的密钥是 profile_path
。因此,您只需将 JSONDecoder
的 keyDecodingStrategy
属性 设置为 .convertFromSnakeCase
即可正确解码:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let movies = try JSONDecoder().decode(MovieCreditResponse.self, from: data!)
} catch {
// Handle error
print(error)
}
此外,通常使用 try!
是非常糟糕的做法。您应该 do-try-catch
并处理任何抛出的错误。
我得到 JSON 其中一个键可以是 nil
。所以,我在数据模型中使用了一个可选的 属性,但是在解码之后,我总是得到 nil
这个 属性,即使在 JSON 中,键值包含一个字符串而不是 nil
。下面是我得到的响应和控制台的输出,我在其中检查写入 profilePath
属性
响应:
{"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}
控制台输出:
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?
}
JSON 文件中的 属性 名称是 profile_path
,但您尝试将其解码为 profilePath
。
您应该添加一个枚举来定义 JSON 键,例如
enum CodingKeys: String, CodingKey {
case profilePath = "profile_path"
// add the other keys as well
}
JSON 中 profilePath
属性 的密钥是 profile_path
。因此,您只需将 JSONDecoder
的 keyDecodingStrategy
属性 设置为 .convertFromSnakeCase
即可正确解码:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let movies = try JSONDecoder().decode(MovieCreditResponse.self, from: data!)
} catch {
// Handle error
print(error)
}
此外,通常使用 try!
是非常糟糕的做法。您应该 do-try-catch
并处理任何抛出的错误。